https://github.com/ElemeFE/element/blob/d419e260d0fc1463ccbc4f5e45e129ec0e972255/src/utils/clickoutside.js
下面的代码是element ui中的clickoutside.js
const on = (function() { if (!Vue.prototype.$isServer && document.addEventListener) { return function(element, event, handler) { if (element && event && handler) { element.addEventListener(event, handler, false); } }; } else { return function(element, event, handler) { if (element && event && handler) { element.attachEvent(‘on‘ + event, handler); } }; } })(); import Vue from ‘vue‘; const nodeList = []; const ctx = ‘@@clickoutsideContext‘; let startClick; let seed = 0; !Vue.prototype.$isServer && on(document, ‘mousedown‘, e => (startClick = e)); !Vue.prototype.$isServer && on(document, ‘mouseup‘, e => { nodeList.forEach(node => node[ctx].documentHandler(e, startClick)); }); function createDocumentHandler(el, binding, vnode) { return function(mouseup = {}, mousedown = {}) { console.log(vnode.context.popperElm) if (!vnode || !vnode.context || !mouseup.target || !mousedown.target || el.contains(mouseup.target) || el.contains(mousedown.target) || el === mouseup.target || (vnode.context.popperElm && (vnode.context.popperElm.contains(mouseup.target) || vnode.context.popperElm.contains(mousedown.target)))){ return; } console.log(binding.expression); if (binding.expression && el[ctx].methodName && vnode.context[el[ctx].methodName]) { vnode.context[el[ctx].methodName](); } else { el[ctx].bindingFn && el[ctx].bindingFn(); } }; } /** * v-clickoutside * @desc 点击元素外面才会触发的事件 * @example * ```vue * <div v-element-clickoutside="handleClose"> * ``` */ export default { bind(el, binding, vnode) { nodeList.push(el); const id = seed++; el[ctx] = { id, documentHandler: createDocumentHandler(el, binding, vnode), methodName: binding.expression, bindingFn: binding.value }; }, update(el, binding, vnode) { el[ctx].documentHandler = createDocumentHandler(el, binding, vnode); el[ctx].methodName = binding.expression; el[ctx].bindingFn = binding.value; }, unbind(el) { let len = nodeList.length; for (let i = 0; i < len; i++) { if (nodeList[i][ctx].id === el[ctx].id) { nodeList.splice(i, 1); break; } } delete el[ctx]; } };
这个是我写的alert.vue
<template>
<div class=‘dialog-alert‘ v-show="alert">
<div class=‘dialog-content‘v-clickoutside="hideAlert">
<div class="dialog-body">{{message}}</div>
<a href="javascript:;" class="dialog-button" @click="hideAlert">确定</a>
</div>
<div class="dialog-mask"></div>
</div>
</template>
<script>
import clickoutside from‘./../directives/vue-directive-clickout.js‘
export default{
props:{
alert:{
type:Boolean,
required: true
},
message:{
type:String,
required: true
}
},
methods:{
hideAlert() {
this.$emit(‘hideAlert‘);
}
},
directives: {
clickoutside
},
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
.dialog-alert {
z-index: 21px;
.dialog-content {
position: absolute;
left: 50%;
top: 50%;
margin-left: -4.6875rem;
margin-top: -1.734375rem;
z-index: 21;
border-radius: .3125rem;
background-color: #fff;
}
.dialog-body,
.dialog-button {
width: 9.375rem;
height: 1.734375rem;
margin: 0 auto;
line-height: 1.734375rem;
}
.dialog-body {
border-bottom: 1px solid #999;
color: #6c6c6c
}
.dialog-button {
color: #ff5000
}
}
.dialog-mask {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
bottom: 0;
z-index: 20;
background: rgba(0, 0, 0, .6)
}
</style>
还有我在login.vue中写的触发条件;loginIn函数是将alert的值改为true,hideAlert是将alert的值设置为false
<button class="btn-login" type="button" @click="loginIn">登录</button>
<alert :alert="alert" message="wowoowow" @hideAlert=‘hideAlert‘></alert>
这里的我的问题就是为什么点击登录的时候,弹窗还出的来;点击的时候hideAlert被执行了 所以应该是false;所以呢我就就行了各种的测试,始终找不到答案。
最后呢?我在走路回家的路上想通了这个问题,因为mouseup、mousedown先执行的,click时间后执行的。有点小难受。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="bbb">点击</div>
<script>
document.getElementById(‘bbb‘).addEventListener(‘click‘, function(){
console.log(‘click‘)
}, false);
document.addEventListener(‘mouseup‘, function(){
console.log(‘mouseup‘)
}, false);
document.addEventListener(‘mousedown‘, function(){
console.log(‘mousedown‘)
}, false);
</script>
</body>
</html>
结果:

测试的结果就是: clickoutside.js
1、当一个指令在同一页面上有多个时;绑定的是document事件;document的时间被重复触发;