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

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

const node = {
level,
parent,
...item,
};
nodes.push(node);
if (item.children) {
const children = this.getNodes(item.children, level + 1, node);
nodes = [...nodes, ...children];
node.children = children.filter(child => child.level === level + 1);
}
});
return nodes;
},
// 遍历 nodes,计算每个节点的状态
getStatus(nodes) {
const status = {};
nodes.forEach((node) => {
const parentStatus = status[node.parent && node.parent.key] || {};
status[node.key] = {
expanded: this.expandedKeys.includes(node.key),
visible: node.level === 0 || (parentStatus.expanded && parentStatus.visible),
};
});
return status;
},
// 切换节点的展开状态
changeExpanded(key) {
const index = this.expandedKeys.indexOf(key);
const expandedKeys = [...this.expandedKeys];
if (index >= 0) {
expandedKeys.splice(index, 1);
} else {
expandedKeys.push(key);
}
this.$emit('update:expandedKeys', expandedKeys);
},
},
};
</script>

展开或折叠节点时,我们只需更新

expanded-keys
status
计算属性便会自动更新,保证关联子节点可见状态的正确。

一切准备就绪,为了度量 Tree 组件的运行性能,我们设定了两个指标。

初次渲染时间 节点展开 / 折叠时间

在 Tree 组件中添加代码如下,使用

console.time
console.timeEnd
可以输出某个操作的具体耗时。


export default {
// ...
methods: {
// ...
changeExpanded(key) {
// ...
this.$emit('update:expandedKeys', expandedKeys);

console.time('expanded change');

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

同时,为了放大可能存在的性能问题,我们编写了一个方法来生成可控数量的节点数据。


<template>
<tree :data="data" :expanded-keys.sync="expandedKeys"></tree>
</template>

<script>
export default {
data() {
return {
// 生成一个有 3 层,每层 10 个共 1000 个节点的节点树
data: this.getRandomData(3, 10),
expandedKeys: [],
};
},
methods: {
getRandomData(layers, count, parent) {
return Array.from({ length: count }, (v, i) => {
const key = (parent ? `${parent.key}-` : '') + (i + 1);
const node = {