在我的情况我有鼠标悬停及移出的事件,我想结合有条件地(例如,只有当用户是具有鼠标的设备上)。
我知道我可以在事件处理程序本身的条件,但将仍然可以分配的事件处理程序是不必要的内存。
有没有办法使事件绑定本身成为条件?
(很清楚,我想要的是能够使事件订阅短路,以便在条件为false时基础的addEventListener操作永远不会发生)
在进行了此讨论之后,看来实现此目标的最佳方法是将v-on绑定到包含您感兴趣的事件的规范对象,并将条件放在此处,如下所示:
<div v-on="{ mouseover: condition ? handler : null, click: ... }">
一些注意事项:
addEventLisetener
将不会发生-这就是我们想要的这意味着将所有事件订阅分组为一个v-on属性,而不是将其拆分为单独的显式绑定(<div @mouseover='...' @click='...'/>)
如果这是一个寿命很长的组件,并且基础数据经常更改(导致重新绑定),则您应注意对订阅(即对应的removeEventListener)的处理,因为在一次绑定通过中进行的订阅将不会在后续绑定中被处理。根据您的用例进行评估...
如果您收到“事件“click”的无效处理程序:获取 null”错误,并且您的处理程序函数需要一些参数,那么您应该将处理程序包装在函数中。
所以这个>
v-on="condition ? { blur: () => handler(params) } : {}"
Run Code Online (Sandbox Code Playgroud)
代替
v-on="condition ? { click: handler(params) } : {}"
Run Code Online (Sandbox Code Playgroud)
从Vue 2.6起可以使用:
<div
@mouseover="enableMouseover ? mouseoverHandler : null"
@click="enableClick ? clickHandler : null"
...
>
Run Code Online (Sandbox Code Playgroud)
事件解析为时
null,绑定将被删除。
https://github.com/vuejs/vue/issues/7349#issuecomment-458405684
更简单的是使用渲染函数。您不需要手动删除侦听器并处理它们。还使用简单的 JS 语法,没有 mixins。
new Vue({
el: "#app",
data: () => ({
counter: 0
}),
methods: {
handleClick() {
this.counter++;
}
},
render(h) {
return h(
"div",
IS_MOBILE_DEVICE
? {}
: {
on: { click: this.handleClick }
},
this.counter
);
}
});
Run Code Online (Sandbox Code Playgroud)
完整示例: https: //codesandbox.io/s/nw6vyo6knj
小智 5
我无法对答案发表评论,因此我添加了自己的答案。
已批准答案中的解决方案 3不起作用 - 缺少括号。在这种情况下,正确的语法是:
@click="enableClick && clickHandler()"
Run Code Online (Sandbox Code Playgroud)
这是工作示例
如果您想做类似的事情,您可以通过在要应用事件的ref上添加 来手动应用事件侦听器,然后在满足条件时element使用它在挂钩中绑定事件侦听器:mounted
标记
<button ref="button">
Mouse Over Me
</button>
Run Code Online (Sandbox Code Playgroud)
Vue实例
new Vue({
el: '#app',
mounted() {
let hasMouse = true;
// If the user has a mouse, add the event listeners
if (hasMouse) {
let button = this.$refs.button
button.addEventListener('mouseover', e => {
this.mouseover = true
})
button.addEventListener('mouseout', e => {
this.mouseover = false
})
}
},
data: {
mouseover: false
}
})
Run Code Online (Sandbox Code Playgroud)
这是一个 JSFiddle:https: //jsfiddle.net/0fderek6/
如果您不喜欢这种方法,您也可以使用 adirective并将条件放在那里,然后您可以将其放置在 a 中mixin以使其可重用:
米辛
const mouseEvents = {
directives: {
mouseEvents: {
bind(el, binding, vnode) {
let hasMouse = true;
if (hasMouse) {
el.addEventListener('mouseover', e => {
vnode.context.mouseover = true
})
el.addEventListener('mouseout', e => {
vnode.context.mouseover = false
})
}
}
}
},
data: {
mouseover: false
}
}
Run Code Online (Sandbox Code Playgroud)
Vue实例
new Vue({
el: '#app',
mixins: [mouseEvents]
})
Run Code Online (Sandbox Code Playgroud)
标记
<button v-mouse-events>
Mouse Over Me
</button>
Run Code Online (Sandbox Code Playgroud)
这是 JSFiddle:https: //jsfiddle.net/nq6x5qeq/
编辑
如果您喜欢这种directive方法,您需要做的就是添加一个unbind钩子来删除侦听器,然后您可以将其binding arg作为事件类型并作为binding value处理程序:
Vue.directive('mouse', {
bind(el, binding) {
if (hasMouse) {
console.log(binding.arg + ' added')
// bind the event listener to the element
el.addEventListener(binding.arg, binding.value)
}
},
unbind(el, binding) {
if (hasMouse) {
console.log(binding.arg + ' removed')
el.removeEventListener(binding.arg, binding.value)
}
}
});
Run Code Online (Sandbox Code Playgroud)
现在您需要做的就是添加每个侦听器,就像使用以下命令一样v-bind:
<div v-mouse:mouseover="mouseOverFunction"></div>
Run Code Online (Sandbox Code Playgroud)
这是 JSFiddle 向您展示其工作原理:https ://jsfiddle.net/59ym6hdb/