项目依赖
{
"dependencies": {
"element-ui": "^2.12.0",
"vue": "2.7.16"
}
}
现象
popover(外层)嵌套的内容区域再嵌套一层popover(内层),当popover都打开了,点父popover(外层)的内容区域但是popover(内层)无法关闭隐藏!
简化代码后效果如下
示例代码
<template>
<div class="popover-example">
<el-popover popperClass="parent-popover">
<template #reference>
<h6>parent-popover reference</h6>
</template>
<div class="parent-popover__content">
<p>parent-popover reference</p>
<p>parent-popover reference</p>
<p>parent-popover reference</p>
<el-popover popperClass="child-popover">
<template #reference>
<h6>child-popover reference</h6>
</template>
<div class="child-popover__content">
<p>parent-popover reference</p>
<p>parent-popover reference</p>
<p>parent-popover reference</p>
<p>parent-popover reference</p>
</div>
</el-popover>
</div>
</el-popover>
</div>
</template>
解决
关键思路
点击popover(内层)内容插槽区域外的执行关闭popover(内层)
利用
element-ui内置v-click-out-side指令
由于popover组件使用频率高,需要对popover进行二次封装处理
./components/base-poopver.vue
<template>
<el-popover
ref="popover"
v-bind="popoverOptions"
v-clickoutslide="onClickOueSide"
v-on="$listeners"
>
<template v-for="(value, name) in $slots" #[name]>
<slot :name="name"></slot>
</template>
</el-popover>
</template>
<script>
import clickOutSide from 'element-ui/src/utils/clickoutside';
export default {
directives: {
clickoutslide: clickOutSide,
},
inheritAttrs: true,
data() {
return {
popperElm: null,
};
},
computed: {
popperClassList() {
let className = 'el-popover-base';
if (this.$attrs.popperClass) {
className += ` ${this.$attrs.popperClass}`;
}
return className;
},
popoverOptions() {
return {
...this.$attrs,
popperClass: this.popperClassList,
};
},
popperId() {
return this.$refs.popover.tooltipId;
},
},
mounted() {
// 【必须】v-clickoutslide 内部使用包含元素
this.popperElm = document.querySelector(`#${this.popperId}`); // 即当前popover点击弹出弹窗元素
},
methods: {
closePopover() {
this.$refs.popover.doClose();
},
onClickOueSide() {
this.closePopover();
},
},
};
</script>
项目使用
<template>
<div class="popover-example">
<base-popover popperClass="parent-popover">
<template #reference>
<h6>parent-popover reference</h6>
</template>
<div class="parent-popover__content">
<p>parent-popover reference</p>
<p>parent-popover reference</p>
<p>parent-popover reference</p>
<base-popover popperClass="child-popover">
<template #reference>
<h6>child-popover reference</h6>
</template>
<div class="child-popover__content">
<p>parent-popover reference</p>
<p>parent-popover reference</p>
<p>parent-popover reference</p>
<p>parent-popover reference</p>
</div>
</base-popover>
</div>
</base-popover>
</div>
</template>
最终效果