如何在Vue.js上捕获自定义指令上的单击事件?

如何在Vue.js上捕获自定义指令上的单击事件?,vue.js,vuejs2,vue-directives,Vue.js,Vuejs2,Vue Directives,我正在尝试学习Vue.js,并来到了一个实践示例,在这个示例中,我需要实现一个自定义指令,而该指令在“v-on”中起作用。 这意味着我需要捕获自定义指令上的click事件并调用一个方法 我想到的模板 <template> <h1 v-my-on:click="alertMe">Click</h1> </template> 点击 问题是我不知道如何在custom指令中捕获click事件。请原谅下面的笨拙代码 <script>

我正在尝试学习Vue.js,并来到了一个实践示例,在这个示例中,我需要实现一个自定义指令,而该指令在“v-on”中起作用。 这意味着我需要捕获自定义指令上的click事件并调用一个方法

我想到的模板

<template>
    <h1 v-my-on:click="alertMe">Click</h1>
</template>

点击
问题是我不知道如何在custom指令中捕获click事件。请原谅下面的笨拙代码

<script>
    export default {
        methods: {
            alertMe() {
                alert('The Alert!');
            }
        },
        directives: {
            'my-on': {
                bind(el, binding, vnode) {
                    console.log('bind');

                    el.addEventListener('click',()=>{
                        console.log('bind');
                        vnode.context.$emit('click');
                    });
                },

            }
        }
    }
</script>

导出默认值{
方法:{
alertMe(){
警报(“警报!”);
}
},
指令:{
“我的天哪”:{
绑定(el、绑定、vnode){
console.log('bind');
el.addEventListener('单击',()=>{
console.log('bind');
上下文。$emit('click');
});
},
}
}
}

有人能帮我理解这是怎么回事吗?我没有找到任何类似的示例。

您需要为指令中发出的事件注册一个侦听器

// emit a custom event
// binding.expression is alertMe
vnode.context.$emit(binding.expression);

// listen for the event 
export default {
    created(){
        this.$on('alertMe', event => { 
            this.alertMe()
        })
    },
    ....
}
这不是调用方法
alertMe
,而是将
alertMe
作为绑定表达式传递给指令:

<h1 v-my-on:click="alertMe">Click</h1>
点击

经过进一步搜索,我找到了这个解决方案:


点击我!
导出默认值{
方法:{
alertMe(){
警报(“警报!”);
}
},
指令:{
“我的天哪”:{
//在挂载时添加事件侦听器。
绑定(el,绑定){
el.addEventListener(binding.arg,binding.value);
},
//在销毁时删除事件侦听器。
解除绑定(el,绑定){
el.removeEventListener(binding.arg,binding.value);
}
}
}
}

正如@Vlad所说,这对我很有效:

                    el.addEventListener('click',()=>{
                    console.log('bind');
                    vnode.context.$emit('click');
这是我的指示:

Vue.directive('showMenu', {
    bind: function (el, binding, vnode) {
        el.addEventListener('click', () => {
            console.log('bind')
            setTimeout(() => {
                this.$emit('toggleDrawer')
            }, 1000)
        })
    }
})

谢谢你,伙计

据我所知,您找到的解决方案是您正在寻找的最佳解决方案。然而,对于那些不太了解Vue.JS的人,我想我应该给出一个快速的解释。我还建议您查看Vue官方文档,了解或了解我的概念

这是Vlad制定的代码,我支持:

<template>
    <h1 v-my-on:click="alertMe">Click me!</h1>
</template>

<script>
    export default {
        methods: {
            alertMe() {
                alert('The Alert!');
            }
        },
        directives: {
            'my-on': {
                bind(el, binding) {
                    let type = binding.arg;
                    let myFunction = binding.value;
                    el.addEventListener(type, myFunction);
                }
            }
        }
    }
</script>

点击我!
导出默认值{
方法:{
alertMe(){
警报(“警报!”);
}
},
指令:{
“我的天哪”:{
绑定(el,绑定){
let type=binding.arg;
让myFunction=binding.value;
el.addEventListener(类型,myFunction);
}
}
}
}
简而言之,基于指令对象定义,Vue指令在它们所附加到的元素的生命周期上被调用。在本例中,定义的函数称为“bind”,因此当元素绑定到DOM中时,指令将调用该函数

此函数接收附加到“el”的元素以及模板“binding”中指令用法的不同内容。在模板的绑定用法中,冒号“:”后面的值是“arg”,在本例中是字符串文字“click”。引号''''内的值是“值”,在本例中是对函数“alertMe”的对象引用

然后,通过获取binding.arg和binding.value(及其各自的内容)定义的变量可用于创建包含在指令所使用的元素“el”内的事件侦听器(el是可修改的)。因此,当元素被创建和绑定时,这个新的事件监听器在由“arg”定义的“click”事件上创建,它将调用由“value”定义的“alertMe”函数

因为修改包含在元素中,所以不必担心在取消绑定时进行清理,因为当元素被销毁时侦听器将被销毁


这是对建议代码中发生的事情的基本描述。要了解有关指令以及如何使用它们的更多信息,请按照建议的链接进行操作。希望这有帮助

@Vlad有一个极好的解决方案

我还要补充一点:如果您想将参数传递给回调函数,那么Vue处理表达式的方式会让您感到困惑。简言之,对于自定义指令,引号之间的任何内容都将被计算并传入结果值(因此,您可以通过binding.value(duh!)获得它),而对于内置指令,至少对于v-on,引号之间的内容将在稍后触发事件时被计算

通过比较自定义指令和内置的v-on指令可能可以最好地说明这一点。假设您有一个与@Vlad完全相同的“my-on”指令,并且您将其与v-on并排使用:

内置:
点击我!

按预期工作,单击按钮时,弹出警报窗口

定制:
点击我!

按钮一显示,警报窗口就会弹出,当您单击它时,事件就会触发,但不会发生任何可见的事件。这是因为“myAlert('haha')”会在绑定(?)后立即计算,因此警报窗口及其值会传递给您的指令(未定义或其他),因为它的值不是一个函数,似乎什么都没有发生。 现在,解决方法是让引号之间的任何东西在求值时返回一个函数,例如v-my-on:click=“()=>{myAlert('haha')}”

希望能有帮助

参考资料:


您能留下一个解释它的答案吗,这样我就可以将它标记为已接受?我正在寻找一个指令,它可以侦听“单击”之类的事件,然后调用指定的方法,就像我在模板中提到的那样。这需要将
isFn:true,//重要!
添加到您的指令对象中。本页的最后一部分:它雌鹿