<template>
<div id="app" style="display: flex; gap: 10px">
<div
v-for="(item, index) in myItems"
:key="index"
class="my-item"
v-click-outside="showClickAway"
>
{{ item }}
</div>
</div>
</template>
Vue.directive("click-outside", {
bind: function (el, binding, vnode) {
el.clickOutsideEvent = function (event) {
// here I check that click was outside the el and his children
if (!(el == event.target || el.contains(event.target))) {
// and if it did, call method provided in attribute value
vnode.context[binding.expression](event);
}
};
document.body.addEventListener("click", el.clickOutsideEvent);
},
unbind: function (el) {
document.body.removeEventListener("click", el.clickOutsideEvent);
}
});
您可以访问:https://codesandbox.io/s/dazzling-ellis-rq5si1?file=/src/App.vue
- 点击红色方框
- 参见控制台
预期的结果实际上非常简单。当在外部单击时,它应该记录在元素外部。如果解决方案在外部点击时可以登录一次,会更酷
我尝试了其他的方法,但是被卡住了。请帮助
我做了一些数学运算,没有在这里打印几个日志:
this.counter++;
if (this.counter % this.myItems.length === 0) {
console.log("showClickAway");
}
而且,我更改了这一行:
if ((!(el === event.target || el.contains(event.target)) && event.target.className !== 'my-item'))
示例:
new Vue({
el: '#app',
data: {
myItems: [1, 2, 3, 4, 5],
counter: 0,
},
methods: {
showClickAway() {
this.counter++;
if (this.counter % this.myItems.length === 0) {
console.log("showClickAway");
}
}
},
directives: {
"click-outside": {
bind: (el, binding, vnode) => {
el.clickOutsideEvent = (event) => {
// here I check that click was outside the el and his children
if ((!(el === event.target || el.contains(event.target)) && event.target.className !== 'my-item')) {
// and if it did, call method provided in attribute value
vnode.context[binding.expression](event);
}
};
document.addEventListener("click", el.clickOutsideEvent);
},
unbind: (el) => {
document.removeEventListener("click", el.clickOutsideEvent);
},
},
},
});
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.my-item {
width: 100px;
height: 100px;
background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app" style="display: flex; gap: 10px">
<div v-for="(item, index) in myItems" v-click-outside="showClickAway" :key="item" class="my-item">
{{ item }}
</div>
</div>