我正在开发一个存在性能问题的 Vue/Vuetify 应用程序。我创建了一个围绕 a standard Vuetify v-data-table
component 的自定义组件。对于少量数据来说,它工作得很好,但如果提供中等到大量数据,则会导致 Firefox 挂起和 Chrome 崩溃。
这是我的代码的稍微简化的版本:
<script>
import ...
export default {
props: {
theValues: Array,
// other props
},
computed: {
theKeys: function() {
return this.schema.map(col => col.col);
},
schema: function() {
return this.theValues[0].schema;
},
dataForDataTable: function() {
console.time('test');
let result = [];
for (let i = 0; i < theValues[0].data.length; i++) {
let resultObj = {};
for (let j = 0; j < theKeys.length; j++) {
// The "real" logic; this causes the browser to hang/crash
// resultObj[theKeys[j]] = theValues[0].data[i][j];
// Test operation to diagnose the problem
resultObj[theKeys[j]] = Math.floor(Math.random() * Math.floor(99999));
}
result.push(resultObj);
}
console.timeEnd('test');
// For ~30k rows, timer reports that:
// Real values can take over 250,000 ms
// Randomly generated fake values take only 7 ms
return result;
},
// other computed
},
// other Vue stuff
</script>
以下是 theValues
实际外观的示例:
[
{
data: [
[25389, 24890, 49021, ...] <-- 30,000 elements
],
schema: [
{
col: "id_number",
type: "integer"
}
]
}
]
我看到的快速代码和慢速代码之间唯一有意义的区别是慢速代码在每次迭代时访问 prop theValues
而快速代码不会触及 Vue 的任何复杂部分。 (它确实使用了 theKeys
,但即使我在函数内部创建 theKeys
的本地深拷贝,性能也不会改变。)
基于此,问题似乎不是数据表组件无法处理我发送的数据量,或者嵌套循环本质上效率太低。我最好的猜测是,从 props 中读取太多内容会在某种程度上减慢 Vue 本身的速度,但我不能 100% 确定这一点。
但我最终确实需要将信息从 Prop 获取到表中。我该怎么做才能以合理的速度加载?
最佳答案
性能问题实际上是循环代码的症状,而不是 Vue 的症状。最昂贵的数据访问位于 dataForDataTable()
的内循环中:
for (i...) {
for (j...) {
theValues[0].data[i][j] // ~50 ms average (expensive)
}
}
// => long hang for 32K items
一种优化方法是在循环外部缓存数组,这可以显着缩短循环执行时间并解决挂起问题:
const myData = theValues[0].data
for (i...) {
for (j...) {
myData[i][j] // ~0.00145 ms average
}
}
// => ~39 ms for 32K items
请注意,使用 JavaScript API 无需循环即可计算出相同的结果。这提供了可读性并减少了代码行数,但性能成本却很小(~1ms)。具体来说,使用Array.prototype.map
将 data
中的每个值映射到通过 Array.prototype.reduce
获得的对象属性在theKeys
上:
theValues[0].data
.map(values => theKeys.reduce((obj,key,i) => {
obj[key] = values[i]
return obj
}, {}))
// => ~40 ms for 32K items
上述时间是在 2016 MacBook Pro - 2.7GHz i7、Chrome 87 上测得的。Codesandbox 演示可能与上述时间存在巨大差异。
关于javascript - 如何在不降低性能的情况下重复访问 Vue prop?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65569982/