Web性能优化之降低渲染次数
SPA应用的优势本来是流畅化的类App体验,但是随着业务功能的增加,代码逐步变得臃肿,性能也会出现瓶颈,因此就进入一个课题-性能优化。
其中一个优化的手段就是降低渲染次数。
这里以React的实际代码为例,当然Angular,Vue类似。
无论是哪个JS框架,实际上都是动态渲染新Dom,而框架带来的组件化将整个页面切割为N个组件,因此渲染更新也就成了局部,但是如果使用不当就会出现重复渲染,多余渲染问题,所以对应就应该降低渲染次数,说白了就是只在该渲染时,该渲染的元素身上,执行渲染。
React下的具体优化措施
React针对类组件提供了 shouldComponentUpdate
钩子,默认情况下props,state只要改变就会re-render,当然还有一种情况就是父组件只要render,子组件也会re-render,即使参数没有变化。
react15.3+
提供了pureComponent类,这个类实现了shouldComponentUpdate
方法,具体实现就是对参数做了浅比较,因此如果没变,就不会执行渲染。对应pureComponent解决类组件的渲染问题,React.memo16.6+
解决的事函数组件的渲染问题,两者目的与实现一样。
似乎,我们把组件都切换到pureComponent或者memo就解决了?肯定不是。
这里的实现是浅比较,如果是基本数据类型,实际上这个比较就简单准确,但是如果是对象引用,就也会存在实际上数据相等,但还是重复刷新的问题,因此取决于参数类型,选择对应的优化手段,最终的措施就是shouldComponentUpdate
控制渲染次数
举个例子
在最近的Web调优中,footer我发现共渲染了7次,该组件依赖了很多个redux的对象,确实也用到了,这时继承pureComponent并不可以解决问题,因为参数是非基本数据类型, 因此我只能根据实际的对象值做业务逻辑判断,确定需要渲染的情况,最终渲染2次,且正确。7/2,优化一大半。
对于页面的复杂交互部分更为明显,越是外围的组件,冗余的渲染,对其本身及N层嵌套的组件都会产生影响,细思恐极。
关于redux的使用不当造成的渲染增加
在react 前端架子中,很多组件会关联了redux,这中间很容易出现一个问题是直接连接的对象过大,比如是个person,但是正如上面所说,person name才是真正需要关心消费的,但是因为关联的过大,person其它属性的变动都会引起这个组件的无端渲染。这种使用就是不当的,因此连接redux,需要在合适的对象,合适的层级上才对。
写在最后
JS操作Dom的代价是高昂的,因此降低操作频次是前端一个努力的目标。