javascript - 如何在不降低性能的情况下重复访问 Vue prop?

标签 javascript performance vue.js vuetify.js

我正在开发一个存在性能问题的 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

demo 1

请注意,使用 JavaScript API 无需循环即可计算出相同的结果。这提供了可读性并减少了代码行数,但性能成本却很小(~1ms)。具体来说,使用Array.prototype.mapdata 中的每个值映射到通过 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

demo 2

上述时间是在 2016 MacBook Pro - 2.7GHz i7、Chrome 87 上测得的。Codesandbox 演示可能与上述时间存在巨大差异。

关于javascript - 如何在不降低性能的情况下重复访问 Vue prop?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65569982/

相关文章:

javascript (safari) - 'undefined' 不是评估 elm.parentNode.remove(elm) 的函数

javascript - 使用数据同位素添加装订线值并设置 div 的高度

JavaScript .length 性能

javascript - 在 VueJS 中使用 Axios - 这个未定义

vue.js - axios 预检失败错误 301 使用 vue.js

vue.js - 如何在Vue中传递包含图像路径的prop?

javascript - 使用easyResponsiveTabs.js时如何解决固定菜单闪烁的问题?

javascript - 隐藏div点击其他

c - 数组性能与 LinkedList 非常相似 - 给出了什么?

php - 如何获得一定半径的地方