前言:最近弄公司的项目,一个问卷的制作工具遇到一些性能问题。问题在于题目数量越多,改变一个题目的配置就越卡顿,在题目数超过50题后,就会感觉到明显的操作卡顿了。
于是开始着手对工具的优化
一、网页制作工具特点
- 类似word一样,所有编辑操作在一个界面内完成
- 一个页面上的所有数据就是一个global对象
- 如不做特殊处理,global对象越大,渲染在页面上的item数量越大,页面就会越卡顿
- 采用vue作响应式框架,采用vuex作数据管理工具
二、思考性能瓶颈
- 实例个数(内存)
- 渲染实例个数(浏览器render)
- 实例复杂度
- 循环调用?
三、案例分析
- 首先把 vuex 的 plugins 去除,保持与线上环境一致。避免无关因素的干扰。
plugins.push(createLogger({ collapsed: true })) - 利用 vuex 的 mutation 在 state 中某个数组增加100个 item
- 用户操作,改变某个 item 的某个 prop
- 观察耗时

- 试图减少 item 个数(减少渲染实例)后,再次观察耗时

- 对比最优速度(只有1个 item 的时候)

- 使用 performance 分析瓶颈

- 点击进去,发现瓶颈所在
问题在于,模板重新render了,而模板内有方法,每改变一个属性会导致整个模板重新计算
- 处理瓶颈
当对话框显示的时候才加载计算该模板
- 最后对比最优速度

性能优化了64倍!!!

四、总结
- 减少渲染实例个数。因为每个实例都会有很大 getter 或者 watch ,适时销毁一些没用的实例可以减少内存消耗的同时减少一些数据渲染在页面上,减少卡顿时间。
- 对话框内的数据尽量在对话框显示后才渲染,使用 v-if 处理。
- 有 option 元素的组件需要注意,是否 option 列表数量过大,或列表数量以 global 对象的 renderList 为准,那么 renderList 数量越多, option 的数量就越大,越有可能造成计算量过大,造成页面卡顿。因此应使用 v-if 懒加载 select 框内的 option 元素,或将 v-if 用于 select 元素或其父元素上。