灵活使用冻结对象提升代码效率
刀刀
4/7/2025
0 字
0 分钟
下面来看一个场景:
点击按钮模拟 100 万条数据,追加到响应式的数组内,然后页面显示该数组的长度。效果如下图所示:
代码如下所示:
js
data() {
return {
datas: []
}
},
methods: {
loadDatas() {
this.datas = this.getDatas()
},
getDatas() {
const result = []
for(let i = 0; i < 100000; i++) {
result.push({
id: i,
name: `name${i}`,
address: {
city: `city${i}`,
province: `province${i}`
}
})
}
return result
}
}
可以看到,它需要一段时间才能执行完毕,这还是快进过的效果。
那么,这个时间与性能的消耗主要在哪里呢?从代码来看,好像是 getDatas
函数耗时最久,因为他要循环 100 万 次。通过调试工具查看结果是否如此:
可以看到,它实际上只耗时了 600 毫秒 ,占全部时间的 8.7%,主要消耗不在它。而它上面的 proxySetter
耗时才是大头,占全部时间的 81.6% 。
层层展开其文件夹,发现有一个 observe
文件夹,它才是耗时的大头。
学过 Vue 底层逻辑和源码的都知道,它是用来做数据的响应式的,遍历数组、对象,通过 Object.defineProperty
方法实现代理和深度劫持,实现响应式数据处理。该方法会深度遍历、递归,因此性能相对较差,耗时更多。
如果去掉响应式,那么它的耗时会不会下降呢?通过 Object.freeze()
方法冻结对象。代码如下所示:
js
data() {
return {
datas: []
}
},
methods: {
loadDatas() {
this.datas = Object.freeze(this.getDatas())
},
getDatas() {
// ...
}
}
如果使用了冻结对象,则数据不再设为响应式,此时运行发现速度变得很快,打印 datas
内的数据,已经没有 get
和 set
做响应式的操作了。
这个优化有利有弊,利处就是提高效率,弊处就是它失去了响应式,修改内容后页面不再更新。因此需要结合实际业务场景,有针对性的做优化。
该优化的实际业务场景可以用于数据给死、不需要再次变量的场景,如新闻列表页面、首页导航等。