学习记录02:提高大型数据列表的性能

通常我们在应用中会请求一些列表数据,比如说用户列表、商品列表、文章列表等等......

而且有时候,我们并不会去修改这些请求回来的列表数据,而只是单纯地去展示它们,或者是把它们保存在全局状态管理器里面(又称之为 Vuex)。请求数据列表的示意代码如下所示:

export default {

  data: () => ({

    users: {}

  }),

  async created() {

    const users = await axios.get("/api/users");

    this.users = users;

  }

};

Vue 在默认情况下,会将数组this.users中的,所有对象的第一层属性设置为响应式数据。

这对于大型的对象数组来说,性能成本非常的高。没错,的确有时候列表数据是有分页的,但总会有一些情况下,是没有进行分页,继而在前端展示的。

一个实际的例子就是谷歌地图的标记点 markers 列表数据,这就是一个拥有很多对象的大型数组。

所以,在一些特定的情况下,如果我们能够阻止 Vue 将这些列表数据设置为响应式的,那么我们就可以为项目带来一些性能上的提升。实际上我们就是可以做到的,通过用Object.freeze方法,将获取到的列表数据在赋值给组件之前,进行冻结:

export default {

  data: () => ({

    users: {}

  }),

  async created() {

    const users = await axios.get("/api/users");

    this.users = Object.freeze(users);

  }

};

记住,同样地可以应用到 Vuex 实践中:

const mutations = {

  setUsers(state, users) {

    state.users = Object.freeze(users);

  }

};

顺便说一下,如果你确实有需要去修改请求得到的列表数据,那么你仍然可以通过创建一个新的数组来实现。举个例子,给原列表数据添加一个同类型元素,可以这么操作:

state.users = Object.freeze([...state.users, user]);

来源:https://juejin.cn/post/6844903766982934535

来深究一下为什么Object.freeze()方法可以做到阻止Vue添加双向数据绑定机制

大家应该都知道Vue是通过Object.defineProperty()来修改属性描述符中的setter和getter的,在getter中收集依赖,在setter的时候触发依赖。

在ES5开始,所有的属性都有了属性描述符。决定是否可以修改一个属性的描述符有两个:

是Writable:决定是否可以修改属性的值;

另一个是Configurable:决定是否可以使用Object.defineProperty()来修改属性描述符,并且也会禁止删除这个属性;

当这两个描述符同时为false时,意味着这个属性完全是一个常量,Vue不能通过Object.defineProperty()来添加双向数据绑定。收集不了依赖,也就做不了双向数据绑定,就少添加很多watcher实例。

执行Object.freeze()会执行Object.seal()并吧所有的属性的writable设置成false。

Object.seal()则会调用Object.preventExtensions()并把configurable设为false。

Object.preventExtensions()则会禁止对象添加新的属性。

最后还有一个疑问,state.users = Object.freeze([...state.users, user]);会不会触发视图更新。

答案是会。users变量是定义在data中的,在Vue初始化initState的时候,会遍历data中的所有属性,添加监听。也就是说我们冻结的是users里面所有的属性,并没有冻结Vue中data,所以替换users会触发双向数据绑定

来源:https://www.jianshu.com/p/56168a779849

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容