前言:
永远不要过早优化
具体项目,具体分析,脱离场景看优化没有什么意义
使用key
对于通过循环生成的列表,应给每个列表项一个稳定且唯一的key,这有利于在列表变动时,尽量少的删除,新增,改动元素,因为diff算法就是通过key值来进行比较的
index作为key值是唯一的,但不够稳定,比如插入某元素,会导致后面的所有元素重新渲染,而我们想要的是只渲染新加的元素
比如有一个列表,我们需要在中间插入一个元素,在不使用 key 或者使用 index 作为 key 会发生什么变化呢?先看个图
如图的 li1 和 li2 不会重新渲染,这个没有争议的。而 li3、li4、li5 都会重新渲染
因为在不使用 key 或者列表的 index 作为 key 的时候,每个元素对应的位置关系都是 index,上图中的结果直接导致我们插入的元素到后面的全部元素,对应的位置关系都发生了变更,所以在 patch 过程中会将它们全都执行更新操作,再重新渲染。
这可不是我们想要的,我们希望的是渲染添加的那一个元素,其他四个元素不做任何变更,也就不要重新渲染
而在使用唯一 key 的情况下,每个元素对应的位置关系就是 key,来看一下使用唯一 key 值的情况下
这样如图中的 li3 和 li4 就不会重新渲染,因为元素内容没发生改变,对应的位置关系也没有发生改变。
这也是为什么 v-for 必须要写 key,而且不建议开发中使用数组的 index 作为 key 的原因
对于展示数据使用冻结对象Object.freeze()
冻结的对象不会被响应化
当观察的对象是嵌套对象的时候,就需要递归
如果对象很多,嵌套结构很深,遍历的时间就会变长
思考:
所有的属性都需要响应式吗?
在原始数据中,有些不需要去响应式的,叫做展示数据,比如商品列表,商品价格图片这些都不能操作的
数据响应式:数据变化后,会自动重新运行依赖该数据的函数(重要)
-
被监控的函数
render、computed回调、watch、watchEffect
-
函数运行期间用到了响应式数据(响应式数据一定是个对象)
-
响应式数据变化会导致函数重新运行
Vue会判断对象是否被冻结Object.isFrozen(),如果为true就不遍历
let obj = {
a: 1,
b: 3
}
/* 冻结对象 */
Object.freeze(obj);
obj.c = 2;
console.log(obj); // {a: 1, b: 3}
/* 判断对象是否被冻结 */
console.log(Object.isFrozen(obj)); // true
判断对象是否被冻结Object.isFrozen()
Object.isFrozen(obj);
冻结前:

冻结后:

相比于冻结前,每个属性都少了get和set方法,渲染速度更快。
使用函数式组件(无状态,无实例)
有些时候,我们一个组件只是需要接受一些prop数据,而不会改变什么东西,这个时候可以用函数式组件 ,函数式组件在渲染的时候能减少一定的脚本运行时间,内存占用也少一些