Vue3中如何为多元素添加双击事件(无需使用@dblclick)
解决方案
方法1:事件委托(推荐,符合Vue数据驱动思想)
在父容器(如ContentListItem的<tr>)上绑定一次双击事件,利用事件冒泡判断触发源是否为目标元素,无需给每个元素单独绑定事件。
修改ContentListItem组件:
<tr @dblclick="handleDblClick"> <td>{{ index + 1 }}</td> <td> <input type="checkbox" class="none-dblclick" /> </td> <td> <span> <svg class="none-dblclick"> <path ... /> </svg> </span> </td> <td>{{ content.name }}</td> </tr>
组件setup中定义处理函数:
import { defineProps } from 'vue' export default { props: ['content', 'index'], setup() { const handleDblClick = (e) => { // 检查点击目标或其父元素是否包含目标类名 const target = e.target.closest('.none-dblclick') if (target) { // 双击逻辑 console.log('双击目标元素', target) // 可根据元素类型区分处理 if (target.tagName === 'INPUT') { // 复选框双击逻辑 } else if (target.tagName === 'SVG') { // 收藏图标双击逻辑 } } } return { handleDblClick } } }
方法2:自定义指令(复用性强)
注册全局或局部自定义指令,给需要绑定双击事件的元素添加指令即可,无需重复编写事件绑定逻辑。
局部注册(ContentListItem组件内)
<script setup> import { defineProps, directive } from 'vue' // 定义自定义指令 const vDblclickAction = directive('dblclick-action', { mounted(el) { const handler = () => { // 双击逻辑 console.log('双击触发', el) // 可根据元素类型做区分处理 } el.addEventListener('dblclick', handler) // 存储handler用于解绑,避免内存泄漏 el._dblclickHandler = handler }, unmounted(el) { el.removeEventListener('dblclick', el._dblclickHandler) } }) const props = defineProps(['content', 'index']) </script> <template> <tr> <td>{{ index + 1 }}</td> <td> <input type="checkbox" v-dblclick-action /> </td> <td> <span> <svg v-dblclick-action> <path ... /> </svg> </span> </td> <td>{{ content.name }}</td> </tr> </template>
全局注册(main.js中)
import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) app.directive('dblclick-action', { mounted(el) { const handler = () => { // 双击逻辑 console.log('全局指令双击触发') } el.addEventListener('dblclick', handler) el._dblclickHandler = handler }, unmounted(el) { el.removeEventListener('dblclick', el._dblclickHandler) } }) app.mount('#app')
注册后,任意组件内直接使用v-dblclick-action即可。
方法3:Ref结合生命周期(谨慎使用,需遵循DOM操作规范)
若坚持使用类名选择器,可在组件onMounted钩子中获取元素绑定事件,同时在onUnmounted中解绑,避免内存泄漏。
<script setup> import { defineProps, onMounted, onUnmounted, ref } from 'vue' const props = defineProps(['content', 'index']) const listItemRef = ref(null) let handlers = [] onMounted(() => { if (listItemRef.value) { const elements = listItemRef.value.querySelectorAll('.none-dblclick') handlers = Array.from(elements).map(el => { const handler = () => { // 双击逻辑 console.log('双击元素', el) } el.addEventListener('dblclick', handler) return { el, handler } }) } }) onUnmounted(() => { handlers.forEach(({ el, handler }) => { el.removeEventListener('dblclick', handler) }) }) </script> <template> <tr ref="listItemRef"> <td>{{ index + 1 }}</td> <td> <input type="checkbox" class="none-dblclick" /> </td> <td> <span> <svg class="none-dblclick"> <path ... /> </svg> </span> </td> <td>{{ content.name }}</td> </tr> </template>
内容的提问来源于stack exchange,提问作者ACS
相关产品推荐
相关产品推荐

