在写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
属性,使其不会被复用。