// HTML部分 <div v-clock> <div v-clickoutside="handleClose"> <button @click="show = !show">点击显示下拉菜单</button> <div v-show="show"> <p>下拉框内容,点击外面区域可以关闭</p> </div> </div> // JS部分 var app = new Vue({ el: '#app', data: { show: false }, methods: { handleClose() { this.show = false; } } }) Vue.directive('clickoutside', { bind: function(el, binding, vode) { function documentHandler (e) { if (el.contains(e.target)) { return false } if (binding.expression) { binding.value(e) } } el.__vueClickOutSide__ = documentHandler document.addEventListener('click', documentHandler) }, unbind: function(el, binding) { document.removeEventListener('click', el.__vueClickOutSide__) delete el.__vueClickOutSide__ } })
要在document上绑定click事件,所以在bind钩子内声明了一个函数documentHandler,并将它作为句柄定在document的click事件上。documentHandler函数做了两个判断,第一个是判断点击的区域是否是指令所在的元素内部,如果是,就跑出函数,不信下继续执行
contains方法是用来判断元素A是否包含了元素 B,包含返回true,不包含返回false
// HTML <div> 父元素 <div>子元素</div> </div> // JS var a = doucment.getElemengById('parent') var b = doucment.getElemengById('children') console.log(A.contains(B)) // true console.log(B.contains(A)) // false
第二个判断是当前 的指令v-clickoutside有没有写表达式,在该自定义指令中,表达 式应该是第一个函数 ,在过滤了内部元素后,点击外面任何区域应该招待用户表达 式中的函数 ,所以binding.value就用来执行上下文methods中指定的函数的