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

时间:2018-01-28 12:00:10

标签: vue.js vuejs2 vue.js-directives

我正在尝试学习Vue.js并且来到一个练习示例,我需要实现一个自定义指令,这个指针可以解决虱子'v-on'。 这意味着我需要在自定义指令上捕获click事件并调用方法。

我想到的模板。

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

问题是我不知道如何捕获自定义指令中的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>

任何人都可以帮我理解这是如何运作的吗?我没有找到任何类似的例子。

5 个答案:

答案 0 :(得分:4)

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

<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>

答案 1 :(得分:2)

据我所知,您找到的解决方案是您所寻找的最佳解决方案。但是,对于那些对Vue.JS不太了解的人,我想我会给出一个简短的解释。我还建议您查看Custom Directives或我的Medium article有关概念的官方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>

简而言之,基于指令对象定义,Vue指令在其所附加元素的生命周期中被调用。在示例中,定义的函数称为“绑定”,因此,当元素绑定到DOM中时,伪指令将调用该函数。

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

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

由于修改内容包含在元素中,因此您不必担心清理未绑定的情况,因为在破坏元素时,监听器也会被破坏。

这是对建议代码中发生的情况的基本描述。要查看有关指令及其用法的更多信息,请遵循建议的链接。希望有帮助!

答案 2 :(得分:1)

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

// 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>

答案 3 :(得分:1)

@Vlad有一个很好的解决方案!

我还想补充一点:如果您想将参数传递给回调,它将以Vue处理表达式的方式使您感到困惑。简而言之,对于自定义指令,对引号之间的所有内容进行求值并传递结果值(因此,您可以通过binding.value(duh!)获得它,而对于内置指令,至少对于v-on ,当事件被触发时,引号之间的内容将在以后进行评估。

也许最好通过在自定义指令和内置v-on指令之间进行比较来证明这一点。假设您有一个与@Vlad完全一样的“ my-on”指令,并且与v-on一起使用:

内置: <h1 v-on:click="myAlert('haha')"> Click me!</h1>

它可以按预期工作,当单击按钮时,会弹出警报窗口。

自定义: <h1 v-my-on:click="myAlert('haha')">Click me!</h1>

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

希望有帮助。

参考:

https://stackoverflow.com/a/61734142/1356473

https://github.com/vuejs/vue/issues/5588

答案 4 :(得分:0)

正如@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)
        })
    }
})

谢谢伙计!