Vue.js 通过v-if安装组件时,Vue组件$el不在dom中

Vue.js 通过v-if安装组件时,Vue组件$el不在dom中,vue.js,vuejs2,vue-component,Vue.js,Vuejs2,Vue Component,我有一个简单的popover组件,它获取其父组件在dom中的位置,然后将自己提升到document.body中,并绝对地定位自己 当我使用v-show显示和隐藏组件时,这一切都非常有效,但是如果我尝试使用v-if,它会抱怨这个.el.parentElement为null 根据定义,调用mounted()时,$el应该在文档中,但通过v-if有条件地呈现它时,情况似乎并非如此 我试过使用,但也没用 我做错什么了吗 以下是我的组件的代码: <template> <div class

我有一个简单的popover组件,它获取其父组件在dom中的位置,然后将自己提升到document.body中,并绝对地定位自己

当我使用v-show显示和隐藏组件时,这一切都非常有效,但是如果我尝试使用v-if,它会抱怨这个.el.parentElement为null

根据定义,调用mounted()时,$el应该在文档中,但通过v-if有条件地呈现它时,情况似乎并非如此

我试过使用,但也没用

我做错什么了吗

以下是我的组件的代码:

<template>
<div class="popover"><slot ></slot></div>
</template>

<script>
export default {
    name: 'pop-over',
    props: ['position', 'anchor', 'offset'],
    methods: {

    },
    mounted() {
        let rect = {};
        let parent = this.$el.parentElement;
        document.body.appendChild(this.$el);

        let offset = {
            x: this.offset ? this.offset.x || 0 : 0,
            y: this.offset ? this.offset.y || 0 : 0
        }


        if (this.position) {
            rect = {
                top: this.position.top,
                left: this.position.left
            }
        } else {
            rect = parent.getBoundingClientRect();
            rect = {
                top: rect.top + window.scrollY,
                left: rect.left + window.scrollX,
                bottom: window.innerHeight - rect.bottom - + window.scrollY,
                right: window.innerWidth - rect.right + window.scrollX
            }
        }


        this.$el.style.left = (rect.left + offset.x) + 'px';

        if (this.anchor == 'below') {
            this.$el.style.top = (rect.top + offset.y) + 'px';
        } else {
            this.$el.style.bottom = (rect.bottom + offset.y) + 'px';
        }
    }
}
</script>

导出默认值{
名称:'弹出',
道具:[“位置”、“锚定”、“偏移”],
方法:{
},
安装的(){
设rect={};
让parent=this.$el.parentElement;
document.body.appendChild(此$el);
let offset={
x:this.offset?this.offset.x | | 0:0,
y:这个。偏移量?这个。偏移量。y | | 0:0
}
如果(这个位置){
矩形={
top:this.position.top,
左:这个。位置。左
}
}否则{
rect=parent.getBoundingClientRect();
矩形={
顶部:rect.top+window.scrollY,
左:rect.left+window.scrollX,
底部:window.innerHeight-rect.bottom-+window.scrollY,
右:window.innerWidth-rect.right+window.scrollX
}
}
这个.$el.style.left=(rect.left+offset.x)+'px';
如果(this.anchor=='below'){
这个.$el.style.top=(rect.top+offset.y)+'px';
}否则{
这个.$el.style.bottom=(rect.bottom+offset.y)+'px';
}
}
}

我在实现弹出窗口时也面临同样的问题。最后,通过以下代码解决:

让elParent=this.$el.parentNode;
如果(!elParent){
让parent=this.$parent;
while(父项和父项$el==此项$el){
父项=父项。$父项;
}
如果(家长){
父项$el.appendChild(本项$el);
elParent=父项$el;
}
}

因此,我所做的是在
v-if=true

之后进行渲染时重新构建dom关系,为什么要执行
document.body.appendChild(this.$el)
?试着在没有那一行的情况下运行代码,看看会发生什么。[编辑以澄清我提出建议的原因]我尝试在我的一个项目中复制这一点。在我将该行添加到代码中之前,v-if和parentElement工作得很好。当您将元素附加到document.body时,您正在将其从原始位置移除,从而更改parentElement。将其附加到body的目的是将其从文档流中移除,因此它将显示在所有其他内容之上。在移动父对象之前,我会先复制一份父对象,这样就不会有问题了。