diff --git a/packages/directives/__tests__/repeat-click.test.tsx b/packages/directives/__tests__/repeat-click.test.tsx index 299f6d5869..67c84c808d 100644 --- a/packages/directives/__tests__/repeat-click.test.tsx +++ b/packages/directives/__tests__/repeat-click.test.tsx @@ -1,8 +1,8 @@ import { mount } from '@vue/test-utils' import { describe, expect, it, vi } from 'vitest' -import sleep from '@element-plus/test-utils/sleep' -import RepeatClick from '../repeat-click' +import RepeatClick, { REPEAT_DELAY, REPEAT_INTERVAL } from '../repeat-click' +const PRESS_TIME = REPEAT_DELAY + REPEAT_INTERVAL let handler: ReturnType const _mount = () => @@ -27,40 +27,28 @@ const _mount = () => ) describe('Directives.vue', () => { - it('click test', async () => { + it('single click', async () => { const wrapper = _mount() const block = wrapper.find('#block') + vi.useFakeTimers() block.trigger('mousedown') - await sleep(330) + vi.advanceTimersByTime(PRESS_TIME - 1) + document.dispatchEvent(new MouseEvent('mouseup')) + expect(handler).toHaveBeenCalledTimes(1) + vi.useRealTimers() + }) + + it('click and hold on', async () => { + const wrapper = _mount() + const block = wrapper.find('#block') + + vi.useFakeTimers() + block.trigger('mousedown') + vi.advanceTimersByTime(PRESS_TIME) document.dispatchEvent(new MouseEvent('mouseup')) - expect(handler).toHaveBeenCalledTimes(3) - }) - - it('time interval between mousedown and mouseup is slightly less than 100ms', async () => { - const wrapper = _mount() - const block = wrapper.find('#block') - - for (let i = 0; i < 10; i++) { - block.trigger('mousedown') - await sleep(99) - document.dispatchEvent(new MouseEvent('mouseup')) - } - - expect(handler).toHaveBeenCalledTimes(10) - }) - - it('time interval between mousedown and mouseup is slightly more than 100ms', async () => { - const wrapper = _mount() - const block = wrapper.find('#block') - - for (let i = 0; i < 10; i++) { - block.trigger('mousedown') - await sleep(101) - document.dispatchEvent(new MouseEvent('mouseup')) - } - - expect(handler).toHaveBeenCalledTimes(10) + expect(handler).toHaveBeenCalledTimes(2) + vi.useRealTimers() }) }) diff --git a/packages/directives/repeat-click/index.ts b/packages/directives/repeat-click/index.ts index d37ede516d..bcfea54701 100644 --- a/packages/directives/repeat-click/index.ts +++ b/packages/directives/repeat-click/index.ts @@ -1,32 +1,37 @@ import type { DirectiveBinding, ObjectDirective } from 'vue' +export const REPEAT_INTERVAL = 100 +export const REPEAT_DELAY = 600 + const RepeatClick: ObjectDirective = { beforeMount(el: HTMLElement, binding: DirectiveBinding) { let interval: ReturnType | null = null - let isHandlerCalled = false + let delay: ReturnType | null = null const handler = () => binding.value && binding.value() const clear = () => { - clearInterval(interval!) - interval = null - - if (!isHandlerCalled) { - handler() + if (delay) { + clearTimeout(delay) + delay = null + } + if (interval) { + clearInterval(interval) + interval = null } - isHandlerCalled = false } el.addEventListener('mousedown', (e: MouseEvent) => { if (e.button !== 0) return + handler() document.addEventListener('mouseup', clear, { once: true }) - - clearInterval(interval!) - interval = setInterval(() => { - isHandlerCalled = true - handler() - }, 100) + clear() + delay = setTimeout(() => { + interval = setInterval(() => { + handler() + }, REPEAT_INTERVAL) + }, REPEAT_DELAY) }) }, }