mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
fix(directives): [repeat-click] Interval time is too short for single clicks (#9466)
* fix(directives): [repeat-click] time is too short for single clicks * fix(test-utils): [repeat-click] increase sleep time Updated times according to PR #9466 * fix(test-utils): [repeat-click] increase test time Updated times according to PR #9466 * chore: update * chore: improve test case Co-authored-by: holazz <2418184580@qq.com>
This commit is contained in:
@@ -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<typeof vi.fn>
|
||||
|
||||
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()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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<typeof setInterval> | null = null
|
||||
let isHandlerCalled = false
|
||||
let delay: ReturnType<typeof setTimeout> | 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)
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user