为什么不在点击外部处理程序内执行选定的检查?您还需要一种将单击的项目传递给处理程序的方法。
<div id="list-item" v-on-click-outside="outSideClickHandler(item)"></div>
outSideClickHandler(item) {
return event => {
if (item.selected) {
// Handle the click outside
}
};
}
像这样调用指令中的处理程序:
binding.value(event);
您没有像您那样获得自定义指令的自动“表达式/语句”绑定v-on
这就是为什么当您想向处理函数传递额外的参数时需要柯里化处理函数。
我的意思是参数传递给v-on
可以是表达式或语句,例如:
@click="handler" - handler is an expression (the function itself)
@click="handler(item)" - handler(item) is a statement
但使用自定义指令时,您只能传递表达式;上面的第二行是不可能的,除非handler()
返回另一个函数。
我认为存在一些混乱,因为您似乎想要一个自定义指令,该指令仅在列表项的这种特定情况下使用,但我上面的解决方案更多的是编写一个您可以使用的通用“点击外部”指令在任何情况下。
另外,我认为如果未选择列表项(出于性能原因?),您不希望指令注册任何事件侦听器。如果是这种情况,那么您可以改用事件委托。
无法有条件地启用/禁用指令,您必须执行类似的操作莫蒂的回答 https://stackoverflow.com/a/50288329/734040,两者都有点混乱。
这似乎可行,但使用自定义指令的重点是编写可重用的 dom 操作代码
您是否反对在指令之外编写 DOM 操作代码? Angular 1 就有这样的理念。除非您想在不同的情况下重用该指令,否则为这种情况编写指令可能会有点过分,只是为了“DOM 操作代码不会污染我的组件”。如果我要编写一个指令,那么我希望它尽可能通用,以便我可以在许多不同的情况下使用它。
在这种情况下我什至不需要传递该项目。因为我在 v-for 中有一个组件,而不是 div,并且我在该组件上绑定了自定义指令,其中处理程序是该组件的方法
然后我不确定为什么你想将其作为指令来实现,反正很少需要它。您只需在中注册正文点击事件即可mounted
钩住并将其取出destroyed
钩。所有点击外部逻辑都可以包含在组件本身内。
如果您主要关心的是不必为每个列表项注册主体单击事件侦听器,您可以执行以下操作:
const handlers = new Map();
document.addEventListener('click', e => {
for (const handler of handlers.values()) {
handler(e);
}
});
Vue.directive('click-outside', {
bind(el, binding) {
const handler = e => {
if (el !== e.target && !el.contains(e.target)) {
binding.value(e);
}
};
handlers.set(el, handler);
},
unbind(el) {
handlers.delete(el);
},
});
您可以更进一步,每当handlers
为非空并在以下情况下删除侦听器handlers
是空的。由你决定。