如何捕获 Vue.js 上自定义指令的点击事件?
How can I capture click event on custom directive on Vue.js?
我正在尝试学习 Vue.js 并来到了一个练习示例,我需要在其中实现一个自定义指令,它可以正常工作 'v-on'。
这意味着我需要在我的自定义指令上捕获点击事件并调用一个方法。
我想到的模板。
<template>
<h1 v-my-on:click="alertMe">Click</h1>
</template>
问题是我不知道如何在自定义指令中捕获点击事件。请原谅下面笨拙的代码。
<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>
任何人都可以帮助我了解这是如何工作的吗?我没能找到任何类似的例子。
您需要为指令中发出的事件注册一个侦听器。
// 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>
经过更多搜索,我找到了这个解决方案:
<template>
<h1 v-my-on:click="alertMe">Click me!</h1>
</template>
<script>
export default {
methods: {
alertMe() {
alert('The Alert!');
}
},
directives: {
'my-on': {
// Add Event Listener on mounted.
bind(el, binding) {
el.addEventListener(binding.arg, binding.value);
},
// Remove Event Listener on destroy.
unbind(el, binding) {
el.removeEventListener(binding.arg, binding.value);
}
}
}
}
</script>
正如@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 的人,我想我会给出一个快速的解释。我还建议您查看有关概念的 Custom Directives or my 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 指令在它们附加到的元素的生命周期中被调用。在示例中,定义的函数称为 "bind",因此指令将在元素绑定到 DOM 时调用该函数。
此函数接收其附加到 "el" 的元素以及模板中指令用法的不同内容 "binding"。在模板中的绑定用法中,冒号“:”之后的值是 "arg",在本例中是字符串文字 "click"。引号 '""' 内的值是 "value",在本例中是对函数 "alertMe" 的对象引用。
然后可以使用通过获取 binding.arg 和 binding.value(及其各自的内容)定义的变量来创建包含在元素 "el" 中的事件侦听器指令用于(el 是可修改的)。因此,当元素被创建和绑定时,这个新的事件侦听器是在 "arg" 定义的 "click" 事件上创建的,它将调用 "value" 定义的 "alertMe" 函数。
因为修改是包含在元素内部的,所以不用担心unbind时的清理,因为元素销毁时监听器也会被销毁。
这是对建议代码中所发生情况的基本描述。要查看有关指令以及如何使用它们的更多信息,请点击建议的链接。希望对您有所帮助!
@Vlad 有一个很好的解决方案!
我还要补充一点:如果你想将参数传递给你的回调,Vue 处理你的表达式的方式会让你感到困惑。简而言之,对于自定义指令,引号之间的任何内容都会被计算并传入结果值(因此,您可以通过 binding.value 获取它(duh!),而对于内置指令,至少对于 v -on,当事件被触发时,引号之间的内容将在稍后计算。
也许这可以通过自定义指令和内置 v-on 指令之间的比较得到最好的证明。假设您有一个 "my-on" 指令完全按照@Vlad 的方式编写,并且您将它与 v-on:
并排使用
内置:
<h1 v-on:click="myAlert('haha')"> Click me!</h1>
按预期工作,单击按钮时,弹出警报 window。
定制:
<h1 v-my-on:click="myAlert('haha')">Click me!</h1>
一旦显示按钮,就会弹出警报 window,当您单击它时,会触发该事件,但不会发生任何可见的事情。这是因为 "myAlert('haha')" 在绑定 (?) 时立即被评估,因此警报 window,并且它的值被传递给您的指令(未定义或其他),因为它的值不是函数,没有似乎发生了。
现在,解决方法是在评估时将引号 returns 之间的任何内容作为函数,例如 v-my-on:click="() => {myAlert('haha')}"
希望对您有所帮助。
参考文献:
我正在尝试学习 Vue.js 并来到了一个练习示例,我需要在其中实现一个自定义指令,它可以正常工作 'v-on'。 这意味着我需要在我的自定义指令上捕获点击事件并调用一个方法。
我想到的模板。
<template>
<h1 v-my-on:click="alertMe">Click</h1>
</template>
问题是我不知道如何在自定义指令中捕获点击事件。请原谅下面笨拙的代码。
<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>
任何人都可以帮助我了解这是如何工作的吗?我没能找到任何类似的例子。
您需要为指令中发出的事件注册一个侦听器。
// 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>
经过更多搜索,我找到了这个解决方案:
<template>
<h1 v-my-on:click="alertMe">Click me!</h1>
</template>
<script>
export default {
methods: {
alertMe() {
alert('The Alert!');
}
},
directives: {
'my-on': {
// Add Event Listener on mounted.
bind(el, binding) {
el.addEventListener(binding.arg, binding.value);
},
// Remove Event Listener on destroy.
unbind(el, binding) {
el.removeEventListener(binding.arg, binding.value);
}
}
}
}
</script>
正如@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 的人,我想我会给出一个快速的解释。我还建议您查看有关概念的 Custom Directives or my 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 指令在它们附加到的元素的生命周期中被调用。在示例中,定义的函数称为 "bind",因此指令将在元素绑定到 DOM 时调用该函数。
此函数接收其附加到 "el" 的元素以及模板中指令用法的不同内容 "binding"。在模板中的绑定用法中,冒号“:”之后的值是 "arg",在本例中是字符串文字 "click"。引号 '""' 内的值是 "value",在本例中是对函数 "alertMe" 的对象引用。
然后可以使用通过获取 binding.arg 和 binding.value(及其各自的内容)定义的变量来创建包含在元素 "el" 中的事件侦听器指令用于(el 是可修改的)。因此,当元素被创建和绑定时,这个新的事件侦听器是在 "arg" 定义的 "click" 事件上创建的,它将调用 "value" 定义的 "alertMe" 函数。
因为修改是包含在元素内部的,所以不用担心unbind时的清理,因为元素销毁时监听器也会被销毁。
这是对建议代码中所发生情况的基本描述。要查看有关指令以及如何使用它们的更多信息,请点击建议的链接。希望对您有所帮助!
@Vlad 有一个很好的解决方案!
我还要补充一点:如果你想将参数传递给你的回调,Vue 处理你的表达式的方式会让你感到困惑。简而言之,对于自定义指令,引号之间的任何内容都会被计算并传入结果值(因此,您可以通过 binding.value 获取它(duh!),而对于内置指令,至少对于 v -on,当事件被触发时,引号之间的内容将在稍后计算。
也许这可以通过自定义指令和内置 v-on 指令之间的比较得到最好的证明。假设您有一个 "my-on" 指令完全按照@Vlad 的方式编写,并且您将它与 v-on:
并排使用内置:
<h1 v-on:click="myAlert('haha')"> Click me!</h1>
按预期工作,单击按钮时,弹出警报 window。
定制:
<h1 v-my-on:click="myAlert('haha')">Click me!</h1>
一旦显示按钮,就会弹出警报 window,当您单击它时,会触发该事件,但不会发生任何可见的事情。这是因为 "myAlert('haha')" 在绑定 (?) 时立即被评估,因此警报 window,并且它的值被传递给您的指令(未定义或其他),因为它的值不是函数,没有似乎发生了。 现在,解决方法是在评估时将引号 returns 之间的任何内容作为函数,例如 v-my-on:click="() => {myAlert('haha')}"
希望对您有所帮助。
参考文献: