Cookbook组件形式:优化 Vue 组件的运行时性能

2020-06-14 06:17:18易采站长站整理
nodes
的值。


export default {
// ...
watch: {
data: {
handler() {
this.nodes = this.getNodes(this.data);
this.status = this.getStatus(this.nodes);
},
immediate: true,
},
// ...
},
// ...
};

这种修改对于实现的功能是没有影响的,那么性能情况如何呢。


first rendering: 490.119140625ms
expanded change: 183.94189453125ms

使用 Performance 工具尝试查找性能瓶颈。

我们发现,在

getNodes
方法调用之后,有一段耗时很长的
proxySetter
。这是 Vue 在为
nodes
属性添加响应式,让 Vue 能够追踪依赖的变化。
getStatus
同理。

当你把一个普通的 JavaScript 对象传给 Vue 实例的

data
选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。

对象越复杂,层级越深,这个过程消耗的时间越长。当我们存在 1w 个节点时,

proxySetter
的时间就会非常长了。

这里存在一个问题,我们不会对

nodes
某个具体的属性做修改,而是每当
data
变化时重新去计算一次。因此,这里为
nodes
添加的响应式是无用的。那么怎么把不需要的
proxySetter
去掉呢?一种方法是将
nodes
改回计算属性,一般情况下计算属性没有赋值行为。另一种方法就是冻结数据。

使用

Object.freeze()
来冻结数据,这会阻止修改现有的属性,也意味着响应系统无法再追踪变化。


this.nodes = Object.freeze(this.getNodes(this.data));

查看 Performance 工具,

getNodes
方法后已经没有
proxySetter
了。

性能指标如下,对于初次渲染的提升还是很可观的。


first rendering: 312.22998046875ms
expanded change: 179.59326171875ms

你可以通过改进后的示例 (Demo4) 来观察组件的性能损耗。

那我们能否用同样的办法优化