如何避免双击时触发单击事件

当一个元素上,同时绑定了双击事件和单击事件,当双击时,会触发单击事件,如何避免双击时触发单击事件?

方法 1:使用 setTimeout 延迟处理单击事件​

通过延迟单击事件的处理时间,避免与双击事件冲突。

<template>
  <button 
    @click="handleClick" 
    @dblclick="handleDoubleClick"
  >
    点击/双击我
  </button>
</template>

<script setup>
import { ref } from 'vue'

const clickTimeout = ref(null)

const handleClick = () => {
  // 清除之前的定时器(防止双击时触发单击)
  if (clickTimeout.value) {
    clearTimeout(clickTimeout.value)
    clickTimeout.value = null
    return
  }

  // 设置新的定时器,延迟执行单击逻辑
  clickTimeout.value = setTimeout(() => {
    console.log('单击事件触发')
    // 执行单击逻辑...
    clickTimeout.value = null
  }, 300) // 300ms 内如果有双击,则不会触发单击
}

const handleDoubleClick = () => {
  // 清除单击定时器,防止单击事件触发
  if (clickTimeout.value) {
    clearTimeout(clickTimeout.value)
    clickTimeout.value = null
  }
  console.log('双击事件触发')
  // 执行双击逻辑...
}
</script>

方法2:使用 v-click-outside 或自定义指令

如果需要在复杂交互中区分单击和双击,可以封装一个自定义指令。

实现方式:

// directives/clickOrDoubleClick.js
export default {
  mounted(el, binding) {
    let clickTimeout = null
    const { value, arg } = binding

    el.addEventListener('click', (e) => {
      if (clickTimeout) {
        clearTimeout(clickTimeout)
        clickTimeout = null
        return
      }

      clickTimeout = setTimeout(() => {
        if (typeof value === 'function') {
          value(e, 'click')
        }
        clickTimeout = null
      }, 300)
    })

    el.addEventListener('dblclick', (e) => {
      if (clickTimeout) {
        clearTimeout(clickTimeout)
        clickTimeout = null
      }
      if (typeof value === 'function') {
        value(e, 'dblclick')
      }
    })
  },
  unmounted(el) {
    el.removeEventListener('click', () => {})
    el.removeEventListener('dblclick', () => {})
  },
}

注册指令​

// main.js
import { createApp } from 'vue'
import App from './App.vue'
import clickOrDoubleClick from './directives/clickOrDoubleClick'

const app = createApp(App)
app.directive('click-or-double-click', clickOrDoubleClick)
app.mount('#app')

使用方式

<template>
  <button 
    v-click-or-double-click="(e, type) => handleClick(e, type)"
  >
    点击/双击我
  </button>
</template>

<script setup>
const handleClick = (e, type) => {
  if (type === 'click') {
    console.log('单击事件')
  } else if (type === 'dblclick') {
    console.log('双击事件')
  }
}
</script>

方法 4:使用 lodash.debounce 或 lodash.throttle(适用于复杂场景)​

如果单击事件逻辑较复杂,可以使用防抖(debounce)或节流(throttle)来优化。

<script setup>
import { ref } from 'vue'
import { debounce } from 'lodash'

const handleClick = debounce(() => {
  console.log('单击事件(防抖处理)')
}, 300)

const handleDoubleClick = () => {
  console.log('双击事件')
}
</script>

<template>
  <button @click="handleClick" @dblclick="handleDoubleClick">
    点击/双击我
  </button>
</template>

注意​​

  • 防抖适用于单击事件,但双击事件仍然需要单独处理。
  • 如果双击事件触发后,单击事件仍然可能被误触发,建议结合 setTimeout 方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值