在我的场景中,我有鼠标悬停和mouseout事件,我想有条件地绑定(例如,仅当用户在具有鼠标的设备上)。
我意识到我可以在事件处理程序本身中具有条件但是仍然会为事件处理程序分配内存,这是不必要的。
有没有办法使事件绑定本身有条件?
(很明显,我想要的是能够使事件订阅短路,因此如果条件为false,则不会发生基础的addEventListener操作)
在this discussion之后,看来实现此目的的最佳方法是将v-on绑定到包含您有兴趣订阅的事件的规范对象,并将条件放在那里:
<div v-on="{ mouseover: condition ? handler : null, click: ... }">
一些说明:
addEventLisetener
不会发生 - 这就是我们想要的<div @mouseover='...' @click='...'/>
)removeEventListener
),因为在一个绑定传递中进行的订阅将不会在后续传递中处理。根据您的用例进行评估......更简单的是使用渲染功能。您无需手动删除侦听器并进行处理。也使用简单的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
);
}
});
如果你想做类似的事情,你可以通过在要应用事件的ref
上添加element
手动应用事件监听器,然后使用它来绑定mounted
钩子中的事件监听器(如果条件满足):
标记
<button ref="button">
Mouse Over Me
</button>
实例视图
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
}
})
这是一个JSFiddle:https://jsfiddle.net/0fderek6/
如果您不喜欢这种方法,您也可以使用directive
并将条件放在那里,然后您可以将它放在mixin
中以使其可重用:
MI信
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
}
}
实例视图
new Vue({
el: '#app',
mixins: [mouseEvents]
})
标记
<button v-mouse-events>
Mouse Over Me
</button>
这是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)
}
}
});
现在你需要做的就是像使用v-bind
一样添加每个监听器:
<div v-mouse:mouseover="mouseOverFunction"></div>
这是JSFiddle向您展示它是如何工作的:https://jsfiddle.net/59ym6hdb/