react 渲染性能优化

作者 :王学禹

导语

react 性能提升的方法之一是尽量减少 DOM 对比和冗余操作,从而减少组件重复渲染;刚开始使用 react 的时候只专注于对于逻辑的处理,导致很多地方会出现重复渲染或者修改很小的地方引发全部或者不相干的区块重新渲染的情况;这次准备逐步对写过的代码进行重新 review ,记录一下对于性能优化的实践。

1. 按需渲染

在非技术层面,可以考虑对页面进行分块按需加载和渲染,即优先请求和渲染页面主体,延迟请求加载非页面主体内容;

如页面分为左右两个区块,左侧区块为页面主体;可以考虑先异步请求左侧数据并进行渲染,在左侧区块渲染成功之后再对右侧辅助区块进行请求和渲染(右侧区块componentDidMount中进行数据请求);同时将左右两侧区块数据分别在各自组件最顶层进行维护,以后互不影响;

2.避免不必要的重复渲染

除去可以对页面进行分块渲染之外,结合react的组件渲染机制,也可以在组件进行更新时进行更细致的优化,目前主要遇到以下两种情况:

2.1.组件组织结构

页面结构的组件化可以方便地进行页面数据的组织;按需渲染的实质是对数据进行分块维护。

比如前面提到的左右结构的页面布局,左侧和右侧的数据不会互相影响,就可以分左右两块进行维护;就好比一个个小国家,数据的流动维护在组件内部,从不或者很少与外界进行交流。

对于那些只用来展示,或者内部数据在生命周期内不会变动的组件我们就可以主动禁止掉组件的更新;

2.2.组件数据更新

对于内部数据可能会发生变化的组件,我们可以通过判断数据是否真的进行了更新从而决定是否进行重新渲染。react也提供了相应的生命周期函数shouldComponentUpdate方法供我们使用。

一个很简单的想法是在shouldComponentUpdate函数中对前后的数据做深检查,遍历所有的属性,如果相等则不进行重新渲染;但是如果在数据结构很复杂的情况下,检查比较的代价是灰常昂贵的,可能性能反倒还不如干脆直接重新渲染。

因此理想状况下我们不希望在shouldComponentUpdate中对数据做深检查。在解决这个问题之前,还需要我们分清js基本数据和引用数据的区别,比如:

// 基本类型
var a = 'hello';
var b = a;
b = 'world';
console.log(a === b);  // false

// 引用类型
var a = ['hello', 'world'];
var b = a;
b.push('!');
console.log(c === d); // true

对于比较复杂的数据类型,变更后直接用‘===’进行比较是没有用的,因为引用相同;如果可以在变更数据的同时产生一个新的引用不同的数据,那么我们就可以直接进行引用的比较从而判断数据是否有变化了,因此可以借助immutable.js(不可变数据结构的思想)的帮助。

immutable.js很好的解决了上面的需求,在数据发生变更后产生一个全新的immutable data(不可变数据),同时通过structural sharing的方案避免了deep clone带来的过多消耗(除了数据变化检测,还能很好的处理数据缓存、回退等);

因此在使用了immutable data来管理我们的数据之后,如果引用数据发生变更,我们通过对比两者引用是否相同即可判断是否需要进行重新渲染;

对此,react提供了react-addons-update来对immutable data进行支持;

同时,react也提供了PureComponent去改进生命周期方法 shouldComponentUpdate,自动对props和state进行浅比较(shadow comparison),检查组件是否需要重新渲染;只有检测到前后state或者前后props发生变化时,PureComponent才会调用 render 方法。

因此通过借助immutable data(updateaddons)+ 浅比较(pureComponent),我们可以更好的避免react组件的重复渲染,从而有效的提高性能。

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏沈唁志

API接口开发简述示例

1492
来自专栏前端学习心得

Ajax原理一篇就够了

1253
来自专栏开源优测

一篇文章让你入门API测试

什么是API API是Application Programming Interface的简写。 实现了两个或多个独立系统或模块间的通信和数据交换能力。 什么是...

2474
来自专栏QQ音乐技术团队的专栏

React v16 新特性实践

我们在对以上新特性经过一段时间的使用过后,通过本文进行一些细节分享和总结。

5438
来自专栏ThoughtWorks

TW洞见〡为什么你的Angular代码很难测试?

Angular推出有好几年的时候了,跟其他的MV*框架相比,它的双向绑定,无须显式声明Model,模块管理,依赖注入等特点都给Web应用开发带来了极大的便利,...

2953
来自专栏开源优测

一篇文章让你入门API测试

什么是API API是Application Programming Interface的简写。 实现了两个或多个独立系统或模块间的通信和数据交换能力。 什么是...

35410
来自专栏Java架构沉思录

优雅实现延时任务之Redis篇

PS:这篇文章昨天已经推送过了,不过忘了标原创,今天标个原创再发一次,昨天看了的可以不用往下看了。

702
来自专栏c#开发者

WCF,Net remoting,Web service

今天看到WCF,说是整合了Net remoting,Web service。。。下面列一下概念。 一 WCF 概括地说,WCF具有如下的优势:    ...

2685
来自专栏BestSDK

微信、美团的APP“404页面”居然是这样的

大多数App都要与服务器进行数据的交换,App向服务器发出数据请求,服务器接收到请求之后向App传输相应数据,App接收成功后显示数据内容,没有接收成功则反馈数...

3189
来自专栏逍遥剑客的游戏开发

WPF工具开发: 第三库选择

1456

扫码关注云+社区