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 条评论
登录 后参与评论

相关文章

来自专栏HTML5学堂

CSS检查工具-CKStyle

HTML5学堂:CSS代码存在压缩工具、检查工具以及重排属性的工具。今天推荐给大家CKStyle这个工具,顺便也来看看其他的一些工具。 各类CSS检查工具 首先...

3766
来自专栏李成熙heyli

性能优化三部曲之二——通用纯前端优化首屏时间

背景: 对构建的改造已经完成,目前构建的能力可以较为灵活地支撑进一步的优化 希望进一步减少首屏时间,将首屏时间控制在2秒以内 页面情况: 优化之前,并没有上报...

3139
来自专栏程序员的知识天地

如何阅读大型前端开源项目的源码,授人以鱼不如授人以渔

目前网上有很多「XX源码分析」这样的文章,不过这些文章分析源码的范围有限,有时候讲的内容不是读者最关心的。同时我也注意到,源码是在不断更新的,文章里写的源码往往...

2911
来自专栏达摩兵的技术空间

14年工作回顾(一)

本文开始会把之前项目中遇到的一些问题进行分类整理,并得出其经验值。也许其本身在今天的技术架构中没有任何实用价值,但在项目开发中能有举一反三的作用。

732
来自专栏向治洪

关于React Native项目在android上UI性能调试实践

我们尽最大的努力来争取使UI组件的性能如丝般顺滑,但有的时候这根本不可能做到。要知道,Android有超过一万种不同型号的手机,而在框架底层进行软件渲染的时候是...

2765
来自专栏JAVA高级架构

网站性能优化实战——从12.67s到1.06s的故事

1633
来自专栏知晓程序

开发 | 一个 Android 开发者的小程序开发之旅

我是一名 Android 开发程序员,以前没有接触过前端开发,直到接手了公司的小程序项目,才开始逐渐接触前端领域。

942
来自专栏地方网络工作室的专栏

MAC 迅雷最新版无限重启BUG的解决方法

今天打开迅雷想下载点东西,但是发现迅雷一直提醒出现错误,无限重启,但不能打开。。。我可是买了会员的啊!这破玩意儿! ? 首先,重启系统,无效。 然后卸载并重新安...

2679
来自专栏進无尽的文章

ReactNative| 开发环境的搭建及工程的创建

下载最新版的Node.js后,一步一步安装即可。注意下载后的文件为 pkg 文件而不是 dmg。

1433
来自专栏Jackson0714

【博客美化】07.添加打赏按钮

35210

扫码关注云+社区