在 Vue.js 中使用无响应数据提升性能

2021-01-28  本文已影响0人  VioletJack

本文节选转载自
作者:黄轶
链接:https://juejin.cn/post/6922641008106668045
来源:掘金

使用 Non-reactive data 非响应式数据,你可以查看这个在线示例

优化前代码如下:

const data = items.map(
  item => ({
    id: uid++,
    data: item,
    vote: 0
  })
)
复制代码

优化后代码如下:

const data = items.map(
  item => optimizeItem(item)
)

function optimizeItem (item) {
  const itemData = {
    id: uid++,
    vote: 0
  }
  Object.defineProperty(itemData, 'data', {
    // Mark as non-reactive
    configurable: false,
    value: item
  })
  return itemData
}
复制代码

还是前面的示例,我们先通过点击 Genterate items 按钮创建 10000 条假数据,然后分别在开启和关闭 Partial reactivity 的情况下点击 Commit items 按钮提交数据,开启 Chrome 的 Performance 面板记录它们的性能,会得到如下结果。

优化前:

image

优化后:

image

对比这两张图我们可以看到优化后执行 script 的时间要明显少于优化前的,因此性能体验更好。

之所以有这种差异,是因为内部提交的数据的时候,会默认把新提交的数据也定义成响应式,如果数据的子属性是对象形式,还会递归让子属性也变成响应式,因此当提交数据很多的时候,这个过程就变成了一个耗时过程。

而优化后我们把新提交的数据中的对象属性 data 手动变成了 configurablefalse,这样内部在 walk 时通过 Object.keys(obj) 获取对象属性数组会忽略 data,也就不会为 data 这个属性 defineReactive,由于 data 指向的是一个对象,这样也就会减少递归响应式的逻辑,相当于减少了这部分的性能损耗。数据量越大,这种优化的效果就会更明显。

其实类似这种优化的方式还有很多,比如我们在组件中定义的一些数据,也不一定都要在 data 中定义。有些数据我们并不是用在模板中,也不需要监听它的变化,只是想在组件的上下文中共享这个数据,这个时候我们可以仅仅把这个数据挂载到组件实例 this 上,例如:

export default {
  created() {
    this.scroll = null
  },
  mounted() {
    this.scroll = new BScroll(this.$el)
  }
}
复制代码

这样我们就可以在组件上下文中共享 scroll 对象了,尽管它不是一个响应式对象。

其实之前在工作中也有同事遇到过类似的问题,后来通过 Object.freeze() 函数提升了一定的性能。

上一篇 下一篇

猜你喜欢

热点阅读