结合lighthouse查看各项数据,不断进行性能优化,可以从代码、打包、部署这三个层面来优化
代码层面
1、v-if和v-show区分使用
- v-if(惰性的)用的条件判断,是惰性的,false的话初始不会渲染,适用于运行很少改变条件
- v-show不管是什么初始都会渲染,用的display: none来控制隐藏,适用于频繁切换条件的
2、computed、watch和methods区分使用
- computed:
- 一个数据受多个数据影响
- 数据要经过开销很大的计算(如遍历一个很大的数组并做大量计算),可以用computed的缓存特性,只有数据发生变化才会重新计算,否则直接返回缓存
- watch:
- 一个数据影响多个数据的
- 数据变化时,需要执行异步或开销大的操作(比如:请求API)
- methods:
- 希望数据要实时更新,不需要缓存
3、v-for避免同时使用v-if(要知道优先级why)
- v-for优先级要比v-if高,每次渲染都要先遍历进行条件判断,增加了计算成本
- 可以在computed提前把v-if的数据项给过滤掉
优先级why:vue在编译模板时,会先检测模板中的指令,将模板解析成AST,再根据AST生成对应的render函数。它会先将v-for指令转换成一个生成Vnode的函数,并生成对应的Vnode数组,再会根据v-if的条件来决定是否渲染每个Vnode
4、v-for循环添加key(会问 什么是diff?why提高速度?)
- 设置唯一的key,能精确找到该数据,数据改变时能较快定位到diff
diff算法目的是找出差异,最小化更新视图,发生在视图更新阶段,当数据发生变化的时候,diff就对比新旧虚拟DOM,只渲染有变化的部分。
- 1.对比是不是同类型标签,不是同类型直接替换
- 2.是同类型标签,就执行patchVnode方法,判断新旧vnode是否相等
- 3.相等就直接返回,不相等就要对比新旧节点,对比原则以新节点为主,主要分为以下几种:
- newVnode和oldeVnode都有文本节点,就用新节点换旧节点
- new有子节点,old没有,就增new的子节点
- new没有子节点,old有,则删
- 都有子节点,则通过updateChildren对比子节点
why提高速度:
- 添加唯一key让diff准确识别每个节点,在列表更新时,可以准确判断出哪些节点被添加、删除、移动
- 有key就可以通过map直接获得值得对比的旧节点的下标
- 如果没有key就要通过循环旧节点数组用sameVnode去判断新节点和旧节点是否值得比较,值得才返回旧节点下标
- 很显然map查找要比循环数组快
5、用Object.freeze()冻结不需要响应式变化的数据
vue初始化时,会对数据进行劫持,将数据都转换成响应式的,但有的时候只是想单纯展示数据,就可以跳过数据劫持