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

2020-06-14 06:17:18易采站长站整理

},
watch: {
nodes: {
// nodes 改变时重新计算 status
handler() {
this.status = this.getStatus(this.nodes);
},
// 初始化 status
immediate: true,
},
// defaultExpandedKeys 改变时重新计算 status
defaultExpandedKeys() {
this.status = this.getStatus(this.nodes);
},
},
methods: {
getNodes(data, level = 0, parent = null) {
// ...
},
getStatus(nodes) {
// ...
},
// 展开或折叠节点时直接修改 status,并通知父组件
changeExpanded(key) {
console.time('expanded change');

const node = this.nodes.find(n => n.key === key); // 找到该节点
const newExpanded = !this.status[key].expanded; // 新的展开状态

// 递归该节点的后代节点,更新 status
const updateVisible = (n, visible) => {
n.children.forEach((child) => {
this.status[child.key].visible = visible && this.status[n.key].expanded;
if (child.children) updateVisible(child, visible);
});
};

this.status[key].expanded = newExpanded;

updateVisible(node, newExpanded);

// 触发节点展开状态改变事件
this.$emit('expanded-change', node, newExpanded, this.nodes.filter(n => this.status[n.key].expanded));

this.$nextTick(() => {
console.timeEnd('expanded change');
});
},
},
beforeCreate() {
console.time('first rendering');
},
mounted() {
console.timeEnd('first rendering');
},
};

使用 Tree 组件时,即使不传

default-expanded-keys
,节点也能正常地展开或收起。


<!-- 节点可以展开或收起 -->
<tree :data="data"></tree>

<!-- 配置默认展开的节点 -->
<tree
:data="data"
:default-expanded-keys="['1', '1-1']"
@expanded-change="handleExpandedChange"
>
</tree>

优化后的性能耗时如下。


first rendering: 91.48193359375ms
expanded change: 20.4287109375ms

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

冻结数据

到此为止,Tree 组件的性能问题已经不是很明显了。为了进一步扩大性能问题,查找优化空间。我们把节点数量增加到 10000 个。


// 生成 10000 个节点
this.getRandomData(4, 1000)

这里,我们故意制造一个可能存在性能问题的改动。虽然这不是必须的,当它能帮助我们了解接下来所要介绍的问题。

将计算属性

nodes
修改为在
data
watcher
中去获取