問題描述
在寫tab切換時遇到了一個問題,以下為簡化後的問題所在的程式碼:
<img v-if="tabIndex === 2" id="t1">
<div v-if="tabIndex === 2" id="t2"></div>
<div v-if="tabIndex === 2" id="t3"></div>
<div v-show="tabIndex === 2" id="t4">
<div id="content"></div>
</div>
當頁面載入時,先向id為content
的div中新增了一些元素:
function addContent() {
const newDiv = document.createElement('div');
newDiv.innerHTML = '123456789';
document.getElementById('content').appendChild(newDiv);
}
- 如果當
tabIndex
為2時執行addContent()
,上述123456789
能夠正常顯示; - 但如果:
- 在此時將
tabIndex
改為1,再將tabIndex
改為2, - 或者在
tabIndex
不為2時執行addContent()
,再將tabIndex
改為2,
這兩種情況下,123456789
都無法正常顯示。
- 在此時將
問題探索
首先嚐試將目標元素輸出到控制檯。在切換tabIndex
前,先獲取原來的元素:
var oldT4 = document.getElementById('t4');
var oldContent = document.getElementById('content');
此時輸出顯然能得到正確的結果。
然後在切換tabIndex
後,再獲取新的元素:
var newT4 = document.getElementById('t4');
var newContent = document.getElementById('content');
console.log(oldT4, newT4);
console.log(oldContent, newContent);
此時會發現:
oldContent
元素雖然能正常輸出,但在頁面上已經不存在了,此時oldContent
僅僅是引用了一個不存在的元素;newContent
元素就是當前頁面上的content
元素,但其中的內容已被清空。newT4
元素就是當前頁面上的t4
元素。oldT4
卻離奇的變為了t2
元素,console.log(oldT4 === document.getElementById('t2'))
的結果為true
。
問題原因
這是因為t4
在tabIndex
切換時,複用了被v-if
隱藏的t2
元素,複用時會重新渲染t4
內的所有內容,這種情況下,動態新增到content
元素中的內容就會被清空。
這裡複用的順序則是從第一個同樣為div的被v-if
隱藏的元素開始複用,即t2
元素。類似的,如果此時進一步將t2
元素的v-if
修改成v-show
,則oldT4
就會去複用t3
元素。
解決方案
要保留content
元素中的內容,可以考慮:
- 將
t2
、t3
的v-if
改成v-show
。 - 如果確實不方便修改
v-if
,則可以給t2
、t3
新增key
屬性,使其不會被複用。