当前位置: 首页 > backend >正文

记一次v-if和key错误使用,导致vue2的内存爆炸修复!

之前写了一个功能,通过v-for渲染数据,但是数据中存在hidden项,则对数据进行隐藏,由于数据显隐采用了v-if,且循环使用的key,用了(index+900)之类的写法,导致虚拟dom的计算量成倍上涨。
具体问题如下:

<template v-if="showFieldList"><template v-for="(item, index) in fieldList"><template v-if="!item.hidden"><!-- 单选框 --><el-col:span="item.span || 8":key="index + 900"v-if="item.type === 'radio'">......</template></template>
</template>

这里犯了两个重大的错误,
第一,key作为vue虚拟dom中递归判断改变的标志,正确的使用key可以节省很多无畏的性能损失。

设置key与不设置key区别
举个例子:

创建一个实例,2秒后往items数组插入数据

<body><div id="demo"><p v-for="item in items" :key="item">{{item}}</p></div><script src="../../dist/vue.js"></script><script>// 创建实例const app = new Vue({el: '#demo',data: { items: ['a', 'b', 'c', 'd', 'e'] },mounted () {setTimeout(() => { this.items.splice(2, 0, 'f')  // }, 2000);},});</script>
</body>

在不使用key的情况,vue会进行这样的操作:
在这里插入图片描述

分析下整体流程:

比较A,A,相同类型的节点,进行patch,但数据相同,不发生dom操作
比较B,B,相同类型的节点,进行patch,但数据相同,不发生dom操作
比较C,F,相同类型的节点,进行patch,数据不同,发生dom操作
比较D,C,相同类型的节点,进行patch,数据不同,发生dom操作
比较E,D,相同类型的节点,进行patch,数据不同,发生dom操作
循环结束,将E插入到DOM中
一共发生了3次更新,1次插入操作

在使用key的情况:vue会进行这样的操作:

比较A,A,相同类型的节点,进行patch,但数据相同,不发生dom操作
比较B,B,相同类型的节点,进行patch,但数据相同,不发生dom操作
比较C,F,不相同类型的节点
比较E、E,相同类型的节点,进行patch,但数据相同,不发生dom操作
比较D、D,相同类型的节点,进行patch,但数据相同,不发生dom操作
比较C、C,相同类型的节点,进行patch,但数据相同,不发生dom操作
循环结束,将F插入到C之前
一共发生了0次更新,1次插入操作

通过上面两个小例子,可见设置key能够大大减少对页面的DOM操作,提高了diff效率

第二,Vue 官方强烈不建议在 v-for 内使用 v-if,因为这会 导致重复计算。改用 computed 过滤数据:

<!-- 错误做法 -->
<div v-for="item in list" v-if="item.isActive">{{ item.text }}</div><!-- 正确做法 -->
<div v-for="item in activeList" :key="item.id">{{ item.text }}</div><script>
export default {computed: {activeList() {return this.list.filter(item => item.isActive);}}
};
</script>

最后修改为如下写法:

<template v-if="showFieldList"><template v-for="(item, index) in activeList"><template><!-- 单选框 --><el-col:span="item.span || 8":key="item.code"v-if="item.type === 'radio'">......</template></template>
</template>activeList() {return this.fieldList.filter(item => !item.hidden);
}

至此,性能问题基本解决。引以为鉴!

http://www.xdnf.cn/news/16924.html

相关文章:

  • 十八、Javaweb-day18-前端实战-登录
  • 11.消息队列
  • 2. 字符设备驱动
  • Docker环境离线安装指南
  • 计算机网络:如何将一个C类网络划分成两个子网
  • 35.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--数据缓存
  • Docker-03.快速入门-部署MySQL
  • 【大模型实战】向量数据库实战 - Chroma Milvus
  • Android 之 蓝牙通信(4.0 BLE)
  • CASAtomic 原子操作详解
  • 1.内核模块
  • 攻防世界-web-csaw-mfw
  • IO流-字节流-FileOutputStream
  • 复现YOLOV5+训练指定数据集
  • 关于Web前端安全防御之安全头配置
  • 最新Android Studio汉化教程--兼容插件包
  • Java Stream API 编程实战
  • MySQL 事务原理 + ACID笔记
  • 【C语言】结构体详解
  • 无人机集群协同三维路径规划,采用冠豪猪优化器(Crested Porcupine Optimizer, CPO)实现,Matlab代码
  • Jetpack Compose for XR:构建下一代空间UI的完整指南
  • C++引用:高效安全的别名机制详解
  • 途游Android面试题及参考答案
  • pytorch 安装
  • 机器翻译的分类:规则式、统计式、神经式MT的核心区别
  • 计算用户日活:从数据设计到可视化的全流程(高频场景题)
  • 深入掌握 ExcelJS:Node.js 中强大的 Excel 操作库
  • RAG 知识库实战指南:基于 Spring AI 构建 AI 知识问答应用
  • GaussDB case when的用法
  • 在win上安装最新的X-anylabeling以及sam2来帮助进行全自动追踪标注