v-dom-portal 的作用
简单来说就是将子组件渲染到父组件以外的位置,尤其当父组件设置了overflow: hidden;
、z-index
等属性时,使用portal
的方式能够让子组件在视觉上“跳出”父组件容器
部分源码:
function getTarget (node = document.body) {
if (node === true) return document.body
return node instanceof window.Node ? node : document.querySelector(node)
}
inserted (el, { value }, vnode) {
const { parentNode } = el
const home = document.createComment('')
let hasMovedOut = false
if (value !== false) {
parentNode.replaceChild(home, el) // moving out, el is no longer in the document
getTarget(value).appendChild(el) // moving into new place
hasMovedOut = true
}
},
当使用指令的组件插入父节点后,执行inserted
方法:
- 原父节点使用一个空的注释节点替换该DOM元素
- 获取
v-dom-portal
指令设置的元素节点(想要挂载的位置),默认为document.body
使用
例如直接在组件上添加v-dom-portal
<my-component v-dom-portal>
content
</my-component>
那么该组件就会被document.body.appendChild(node)
添加到文档中
问题
当切换路由时,该组件依然存在,没有从页面中消失
- 它的父级组件卸载后,依然没有消失
- 使用
beforeDestroy
配合v-if
也没用
解决方式:
手动删除v-dom-portal
绑定的元素
在Vue,可以使用 ref 引用组件,调用 **remove()
**方法删掉
<my-component
ref="DOM_PORTAL"
v-dom-portal>
content
</my-component>
beforeDestroy () {
this.$refs['DOM_PORTAL'].remove() // 使用原生DOM元素的删除方法
},