比如,
mounted () {
document.body.appendChild(this.$el);
// insertAdjacentElement
// insertBefore
},
這幾行代碼會導致 dom 元素位置 與 VNode 期望的位置不一致
比如:
---------------------------------------
父組件:
div(id='p')
h1 第1個
button(@click="add") 新增
p(v-for="(item,index) in list", :key="index")
| 第 {{item}} 個元素
ccc
---js部分
methods: {
add () {
this.list.push(1);
}
}
---------------------------------------
子組件 ccc:
div
| 我是document.body.append的元素
---js部分
mounted () {
document.body.appendChild(this.$el);
// insertAdjacentElement
// insertBefore
}
---------------------------------------
本來 ccc 在VNode 中的位置其父 parent 是 id 為 p 的div 元素, 然后由於在 mounted 中,$el的位置發生了移動,導致其實際的位置發生了改變,父節點變為 body 元素。
這將導致 父組件中的 v-for p 元素,渲染失敗
原因:
在點擊 父組件 按鈕是,會觸發 組件的update, 這將會導致新的元素會 insert 到dom樹中,這段代碼在 vue 源碼,patch.js 中
function insert (parent, elm, ref$$1) {
if (isDef(parent)) {
if (isDef(ref$$1)) {
if (ref$$1.parentNode === parent) {
nodeOps.insertBefore(parent, elm, ref$$1);
}
} else {
nodeOps.appendChild(parent, elm);
}
}
}
在插入新的 p 元素時, 會執行這段代碼, 三個參數 分別為: div(id='p'), p 元素自身, ref$$1 為 ccc 的$el
ref$$1.parentNode === parent
由於 ccc 的$el 的parent 發生了變化,導致這行判斷失效, 渲染失敗。