解决iview的Tree控件因数据量过多导致页面卡顿

解决iview的Tree控件因数据量过多导致页面卡顿

问题前后效果对比

问题如下,点击切换公司时,要延迟3s左右才请求接口获取数据:
问题动图

修复后的效果:
请添加图片描述

项目背景

在pc某管理系统项目中,需要对客户的组织架构信息进行列举,并点击可查看对应的客户人员信息【如下图所示】

在这里插入图片描述

发现问题

在官网添加了该组件,并设置了render属性,给每一个公司都设置前缀icon,结果在预览时发现点击切换公司时,会有3-5s的一个卡顿,然后再请求接口,总数据才460条,正常情况下是不会出现这么大的延迟响应。

排查问题

经过反复的测试之后(1 hours later…),发现是组件的 :render="renderContent 这个属性导致的卡顿,取消该属性后再切换公司基本就在20ms内。
思路:页面卡顿的很大一部分原因是因为线程阻塞导致的,这时我们就需要排查哪里有长任务
通过分析performance面板的火焰图发现有一条remove(右边显示这些方法来自 vue.runtime.esm.js)方法,这个方法是 Vue 内部递归响应式的方法

为什么这些方法会长时间占用主线程呢?在 Vue 性能优化中有一条:不要将复杂对象丢到 data 里面,否则Vue 会深度遍历对象中的属性添加 getter、setter(即使这些数据不需要用于视图渲染),进而导致性能问题。
在这里插入图片描述
在这里插入图片描述

解决问题

将data里定义的响应式变量,变为为Non-reactive data(避免 Vue 递归响应式)
转为 Non-reactive data,主要有三种方法:

  • 数据没有预先定义在 data 选项中,而是在组件实例 created 之后再动态定义 this.deptArr (没有事先进行依赖收集,不会递归响应式);
  • 数据预先定义在 data 选项中,但是后续修改状态的时候,对象经过 Object.freeze 处理(让 Vue 忽略该对象的响应式处理,测试无效);
  • 数据定义在组件实例之外,以模块私有变量形式定义(这种方式要注意内存泄漏问题,Vue 不会在组件卸载的时候销毁状态,测试该方法定义的变量不能在template中使用);

这里我们使用第一种方法,将 deptArr改成 Non-reactive data 试一下:

created() {
	this.deptArr = [] // 此变量不在data的return定义,直接在created这里赋值
	this.getDeptTree();
},
methods:{
	getDeptTree() {
		this.$api.sysset.getCustomTree({
			name: this.customObj.customName,
			userId: this.customObj.userId
		}, res => {
			this.deptArr = res.data;
		})
	},
}

然后就发现页面回复了正常,就只是在初始化的时候,数据渲染比较慢,后面切换不同公司都很流畅。后续可能会更新其他解决方法,这个只是一个比较快速的临时方案,如果有大量数据,还是考虑虚拟列表、懒加载等。

有什么问题欢迎评论讨论!

  • 16
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TuoMei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值