简单想应该怎么实现? 1、肯定是给document增加一个click事件监听 2、当发生click事件的时候判断是否点击的当前对象 结合着本思路和指令咱们来实现。(文章最后面有效果图)
简单介绍vue指令
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。unbind:只调用一次,指令与元素解绑时调用。
接下来我们来看一下钩子函数的参数 (即 el、binding、vnode 和 oldVnode)。
代码实现
创建指令对象,分析放在代码中
复制代码
<template>
<div>
<div class="show" v-show="show" v-clickoutside="handleClose">
显示
</div>
</div>
</template>
<script>
const clickoutside = {
// 初始化指令
bind(el, binding, vnode) {
function documentHandler(e) {
// 这里判断点击的元素是否是本身,是本身,则返回
if (el.contains(e.target)) {
return false;
}
// 判断指令中是否绑定了函数
if (binding.expression) {
// 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法
binding.value(e);
}
}
// 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
el.__vueClickOutside__ = documentHandler;
document.addEventListener('click', documentHandler);
},
update() {},
unbind(el, binding) {
// 解除事件监听
document.removeEventListener('click', el.__vueClickOutside__);
delete el.__vueClickOutside__;
},
};
export default {
name: 'HelloWorld',
data() {
return {
show: true,
};
},
directives: {clickoutside},
methods: {
handleClose(e) {
this.show = false;
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.show {
width: 100px;
height: 100px;
background-color: red;
}
</style>
这个方法目前发现是有问题的, 实现不了点击一个按钮弹出一个弹框,点击弹框外的位置关闭弹框的需求,
究其原因,就是点击按钮的时候就相当于点击了弹框外的地方。
解决办法:阻止冒泡
点击空白处隐藏弹出层的原理是在 document 上绑定事件来隐藏弹出层,这样点击任何元素的时候都会冒泡到 document 上,都会执行隐藏弹出层的功能,所以我们只要在不需要隐藏弹出层的元素上阻止冒泡即可。
<div class="header-icon" @click.stop="editNotice">
<i class="iconfont icon-bianji1"></i>
</div>
<div class="content" v-clickoutside="handleCloseNoticeEdit">
<div :contenteditable="isNoticeEdit" :class="{ editborder: isNoticeEdit }" class="outEditableDiv">
<p>1、颜色区分:可点击或者可选择部分鼠标放上去需要变色,已做颜色区分的按钮除外。</p>
<p>2、工作项编号全系统唯一,编号为:(项目标识+数字(1,2,3逐渐增加))。</p>
<p>3、工作项状态有:阶段(打开、进行中、已完成),里程碑(未完成、已完成),需求(打开、进行中、已完成、关闭),任务(打开、进行中、已完成、关闭)。</p>
<!-- <p>4、一个父计划可对应多个子计划或者对应多个工作项,一个计划只能有一个父计划,一个工作项只能有一个父工作项。</p>
<p>5、依赖关系存在于需求和任务,需求和需求,任务和任务之间的关系。</p> -->
</div>
</div>
效果图: