业务场景中遇到了外部单页需要手动关闭主页面的所有的 Element Dialog 弹窗的场景,解决方法是遍历 $root 节点树,找到已经打开的 Dialog 组件,调用它的函数,因为如果只是 JSDom 去修改 Style 是不行的,内部维护的数组会错乱产生意料之外的bug。
- 思路就是去遍历挂载到 Vue 上的所有实例,this.$root 可以获取到根节点
- 我去查看了源码,发现 Dialog 组件使用了
ref='dialog'
,那么我们只需要找到这个实例 - 去判断当前打开的 Dialog 组件,也就是
visible === true
的实例 - 查找到之后,调用原生的关闭事件,就不会产生模态窗一直存在的 bug(包括其它的不可预见的 bug)
- 由于当前的项目一次性只会有一个 Dialog 打开,所以查询到一个以后我就不再遍历了(解决性能)
- 调用下面函数时候
removeDialog (this)
,需要把 this 传入,因为这个函数没有写在.vue
文件中
const removeDialog = (that:any) => {
const childArr = [...that.$root.$children]
const refName = 'dialog'
let _is = false
// 广度优先遍历所有的节点
const bfs = () => {
while (childArr.length) {
// * 队头出队
const _item = childArr.shift()
const _$ref = _item.$refs[`${refName}`]
if (_$ref && _item.visible) {
_is = true
_item.handleClose && _item.handleClose()
}
// * 默认全局只同时打开一个弹窗,如果有多个的情况就不使用 _is
if(_is) return
// * 把队头的 children 依次入队
_item.$children.forEach(child => {
childArr.push(child)
});
}
}
bfs()
}