问题描述

在写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

问题原因

这是因为t4tabIndex切换时,复用了被v-if隐藏的t2元素,复用时会重新渲染t4内的所有内容,这种情况下,动态添加到content元素中的内容就会被清空。 这里复用的顺序则是从第一个同样为div的被v-if隐藏的元素开始复用,即t2元素。类似的,如果此时进一步将t2元素的v-if修改成v-show,则oldT4就会去复用t3元素。

解决方案

要保留content元素中的内容,可以考虑:

  1. t2t3v-if改成v-show
  2. 如果确实不方便修改v-if,则可以给t2t3添加key属性,使其不会被复用。
作者:|longxiaoming|,原文链接: https://www.cnblogs.com/lxm-cnblog/p/17312047.html

文章推荐

设计模式之订阅发布模式

缓存更新的四种策略及选取建议

Rocky 9 Linux 平台 vim 9.0 源码包编译安装踩坑记录

Java 网络编程 —— 非阻塞式编程

谈谈selenium中的clear后输入内容异常的处理

Java并发(一)----进程、线程、并行、并发

用 Go 剑指 Offer 12. 矩阵中的路径

Redis集群介绍及测试思路

.NET生成MongoDB中的主键ObjectId

面试-js 中的 this

Spring Boot中如何优雅地实现异步调用?

K8S 性能优化 - OS sysctl 调优