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

相关文章

来自专栏Java技术分享

关于RBAC(Role-Base Access Control)的理解

基于角色的访问控制(Role-Base Access Control) 有两种正在实践中使用的RBAC访问控制方式:隐式(模糊)的方式和显示(明确)的方式。 今...

1835
来自专栏闻道于事

Spring技术内幕:设计理念和整体架构概述

1273
来自专栏鸿的学习笔记

分布式系统下如何进行数据复制?(上)

在开始讨论数据复制之前,我们需要一个理由为什么要进行数据复制?数据复制显然会给应用带来更高的复杂性,那么我们给出最大理由就是数据复制可以备份数据,使得节点挂掉的...

901
来自专栏前端架构与工程

《微信小程序七日谈》- 第四天:页面路径最多五层?导航可以这么玩

《微信小程序七日谈》系列文章: 本系列的文章并非初学教程,而是笔者在具体开发过程中遇到的问题以及部分解决方案。 微信小程序提供导航相关的API: wx.nav...

28410
来自专栏WindCoder

ubuntu14.04安装了im-switch后系统设置中不见了语言支持

im-switch与语言支持不兼容,两者只能取其一,安装其一,若另一个存在则会被卸载。

561
来自专栏大数据

大数据开发如何规避细节问题,换一个角度来解决常见的细节问题

5.开发细节 5.1工程结构讲解 本书共一个系统架构,二个产品模块(离线和实现),四个项目包:Stormanalyse,Loggenerator, ClickS...

1839
来自专栏阿杜的世界

10个常见软件架构

原文参见:10 Common Software Architectural Patterns in a nutshell

190
来自专栏me的随笔

使用Visual Studio 2015 Community 开发windows服务

  昨天研究在.NET下开发Windows服务程序,期间遇到一些小问题,这里仅将自己的开发过程和需要注意的地方写下和广大网友分享……

472
来自专栏互联网杂技

Angular 1 vs. Angular 2 深度比较

AngularJS 2 尽管还在Alpha阶段,但主要功能和文档已经发布。让我我们了解下Angular 1 和 2 的区别,以及新的设计目标将如何实现。 Ang...

32910
来自专栏安恒信息

预警 | Struts2 REST插件存在远程代码执行漏洞(CVE-2017-9805)

漏洞描述 Struts2 是 Apache 软件基金会负责维护的一个基于MVC设计模式的 Web 应用框架开源项目。 Struts2的REST插件使用带有XSt...

33114

扫码关注云+社区