在react开发中,经常会遇到组件重复渲染的问题,父组件一个state的变化,就会导致以该组件的所有子组件都重写render,尽管绝大多数子组件的props没有变化

render什么时候会触发

首先,先上一张react生命周期图:

这张图将react的生命周期分为了三个阶段:生成期、存在期、销毁期,这样在create、props、state、unMount状态变化时我们可以清楚的看到reacte触发了哪些生命周期钩子以及什么时候会render。

如果我们需要更改root的一个state,使绿色组件视图更改

如果你写过vue,你会发现组件更新是如上图那样的(视图指令已编译为修改视图的函数存放在绑定的state里的属性里,所以能够做到靶向修改),而react会以组件为根,重新渲染整个组件子树,如下图(绿色是期望的render路径,橙色是无用render):

所以在react里,我们探讨的render性能优化是react调用render的路径如下:

如何避免这些不必要的render:

shouldComponentUpdate

shouldComponentUpdate(nextProps, nextState)

使用shouldComponentUpdate()以让React知道当前状态或属性的改变是否不影响组件的输出,默认返回ture,返回false时不会重写render,而且该方法并不会在初始化渲染或当使用forceUpdate()时被调用,我们要做的只是这样:

shouldComponentUpdate(nextProps, nextState) {return nextState.someData !== this.state.someData
}

但是,state里的数据这么多,还有对象,还有复杂类型数据,react的理念就是拆分拆分再拆分,这么多子组件,我要每个组件都去自己一个一个对比吗??不存在的,这么麻烦,要知道我们的终极目标是不劳而获-_-

React.PureComponent

React.PureComponent 与 React.Component 几乎完全相同,但 React.PureComponent 通过props和state的浅对比来实现 shouldComponentUpate()。如果对象包含复杂的数据结构,它可能会因深层的数据不一致而产生错误的否定判断(表现为对象深层的数据已改变视图却没有更新)

关注点:

  • 无论组件是否是 PureComponent,如果定义了 shouldComponentUpdate(),那么会调用它并以它的执行结果来判断是否 update。在组件未定义 shouldComponentUpdate() 的情况下,会判断该组件是否是 PureComponent,如果是的话,会对新旧 props、state 进行 shallowEqual 比较,一旦新旧不一致,会触发 update。
  • 浅判等 只会比较到两个对象的 ownProperty 是否符合 Object.js() 判等,不会递归地去深层比较---源码
const hasOwnProperty = Object.prototype.hasOwnProperty;/*** inlined Object.is polyfill to avoid requiring consumers ship their own* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is*/
function is(x: mixed, y: mixed): boolean {// SameValue algorithmif (x === y) { // Steps 1-5, 7-10// Steps 6.b-6.e: +0 != -0// Added the nonzero y check to make Flow happy, but it is redundantreturn x !== 0 || y !== 0 || 1 / x === 1 / y;} else {// Step 6.a: NaN == NaNreturn x !== x && y !== y;}
}/*** Performs equality by iterating through keys on an object and returning false* when any key has values which are not strictly equal between the arguments.* Returns true when the values of all keys are strictly equal.*/
function shallowEqual(objA: mixed, objB: mixed): boolean {if (is(objA, objB)) {return true;}if (typeof objA !== 'object' || objA === null ||typeof objB !== 'object' || objB === null) {return false;}const keysA = Object.keys(objA);const keysB = Object.keys(objB);if (keysA.length !== keysB.length) {return false;}// Test for A's keys different from B.for (let i = 0; i < keysA.length; i++) {if (!hasOwnProperty.call(objB, keysA[i]) ||!is(objA[keysA[i]], objB[keysA[i]])) {return false;}}return true;
}
  • 至于复杂数据结构,用Object.key()获取下key,然后key和对应的value都是基础类型数据,就是算是简单数据结构,不然就是复杂

针对以上规则我们在项目开发种可以做出如下优化:

尽量将复杂类型数据(ArrayList)所关联的视图单独拆成PureComonent有助于提高渲染性能,比如表单、文本域和复杂列表在同一个 render() 中,表单域的输入字段改变会频繁地触发 setState() 从而导致 组件 重新 render()。而用于渲染复杂列表的数据其实并没有变化,但由于重新触发 render(),列表还是会重新渲染。

react-immutable-render-mixin

我想复杂数组没变化时也不要render(), 那你用react-immutable-render-mixin,来,我们看看插件的介绍:

Users are urged to use PureRenderMixin with facebook/immutable-js. If performance is still an issue an examination of your usage of Immutable.js should be your first path towards a solution. This library was created from experimentations with Immutable that were ultimately erroneous; improper usage of Immutable.js ?. Users should be able to achieve maximum performance simply using PureRenderMixin.


译:不能以正确的姿势来使用immutable-js做优化,你就不要瞎折腾了,用它react-immutable-render-mixin就行了

它和ProComponent原理一样,唯一的区别就是新旧数据的对比,react-immutable-render-mixin用了immutable-js 的is()方法去做对比,性能强,复杂类型数据也能对比(这里不对immutable-js做讨论,一篇很不错的文章Immutable 详解及 React 中实践),相比于React.PureComponent更方便---源码

import Immutable from 'immutable';const is = Immutable.is.bind(Immutable);export default function shallowEqualImmutable(objA, objB) {if (objA === objB || is(objA, objB)) {return true;}if (typeof objA !== 'object' || objA === null ||typeof objB !== 'object' || objB === null) {return false;}const keysA = Object.keys(objA);const keysB = Object.keys(objB);if (keysA.length !== keysB.length) {return false;}// Test for A's keys different from B.const bHasOwnProperty = Object.prototype.hasOwnProperty.bind(objB);for (let i = 0; i < keysA.length; i++) {if (!bHasOwnProperty(keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {return false;}}return true;
}

用法很多,我喜欢Decorator:

import React from 'react';
import { immutableRenderDecorator } from 'react-immutable-render-mixin';@immutableRenderDecorator
class Test extends React.Component {render() {return <div></div>;}
}

react如何通过shouldComponentUpdate来减少重复渲染相关推荐

  1. react 中渲染html_如何在React中识别和解决浪费的渲染

    react 中渲染html by Nayeem Reza 通过Nayeem Reza 如何在React中识别和解决浪费的渲染 (How to identify and resolve wasted r ...

  2. Androud 如何有效减少重复代码

    前言 重复的代码一直都是可维护性的大敌,重构的重要任务之一也就是要去除掉重复的代码,有效的减少重复代码,可以大大提高软件的扩展性. 在Android开发中,很容易产生重复的代码.因为Android是组 ...

  3. 【React深入】深入分析虚拟DOM的渲染原理和特性

    导读 React的虚拟DOM和Diff算法是React的非常重要的核心特性,这部分源码也非常复杂,理解这部分知识的原理对更深入的掌握React是非常必要的. 本来想将虚拟DOM和Diff算法放到一篇文 ...

  4. 翻译 | 关键CSS和Webpack: 减少阻塞渲染的CSS的自动化解决方案

    原文地址: Critical CSS and Webpack: Automatically Minimize Render-Blocking CSS 原文作者: Anthony Gore 译者: 蜗牛 ...

  5. AntV中的饼状图重复渲染问题解决

    场景 在使用AntV的饼状图时,在页面加载完之后js中会ajax请求一次后台数据, 有一个时间的选择框,选择时间后点击搜索会再次执行ajax请求一次. 效果如图: 可是最终导致的后果是饼状图重复渲染. ...

  6. OpenGL 重复渲染

    OpenGL重复渲染 OpenGL重复渲染简介 源代码剖析 主要源代码 OpenGL重复渲染简介 想象一下,你想渲染一个巨大的军队移动的场景.你有一个士兵模型,你想渲染几千名士兵.第一种方法 - 正面 ...

  7. db设计专用excel_独家|自卸车如何实现侧板结构快速设计,减少重复工作?

    作者| 张凯 汉阳专用汽车研究所科研技术部工程师 主要从事专用汽车产品结构仿真与轻量化 随着城市发展的步伐不断加快,适用于各种工况的自卸车.城市渣土车市场需求量不断增大. 目前市场自卸车车厢主要有两种 ...

  8. GridView 重复渲染问题

    GridView 重复渲染问题 在使用GridView的时候由于本身机制问题,经常在加载的时候会多渲染一些内容,而这些这些内容又不是我们需要的,解决起来又很麻烦,在网上搜了很多方法都不管用,所以整理结 ...

  9. 论文降重有效减少重复率修改的方法

    今年,学校对论文检测的似乎比往年更加严格,对文章的重复率的要求也是再创新高,有些高校甚至要求重复率低于8%,所以对于学生掌握一些论文降重有效减少重复率修改的方法非常必要,具体方法小编整理如下:   一 ...

最新文章

  1. CSS3 Media Queries:移动 Web 的完美开端
  2. 高项的项目管理ITTO(PMP第五版)
  3. Spark Streaming介绍,DStream,DStream相关操作(来自学习资料)
  4. 几款浏览器JavaScript调试工具
  5. 软件测试工程师的核心竞争力是什么
  6. Openlayers4加载天地图
  7. Java实用教程(第5版)参考答案
  8. mysql 在线语法检查工具_「mysql 管理工具」五大开源MySQL管理工具! - seo实验室
  9. 计算机考研数据结构高分笔记,2021版天勤计算机考研高分笔记系列:数据结构高分笔记(第9版)...
  10. 采用qt技术,开发OFD电子文档阅读器
  11. 5W1h分析法分析---play框架
  12. CPU、OpenGL/DirectorX、显卡驱动和GPU之间的关系
  13. bgp高防-服务器单线、双线、三线、BGP线路哪个更好?
  14. 在线英语广播==好好学习,天天向上
  15. 使用 SendARP 获取 MAC 地址
  16. 一、FreeRTOS简介
  17. 记录来到结算页面的客户
  18. 阴阳师服务器维护3月14,阴阳师手游抢先体验服3月14日维护更新公告
  19. 关于Oralce OAM/OIM及与P6/Unifier 集成SSO的想法
  20. shell 脚本处理多行文本的记录 -- awk

热门文章

  1. 一个小型的网页抓取系统的架构设计
  2. Openssl asn1parse命令
  3. jQuery滑动效果实例
  4. hiho一下120周 后缀数组一·重复旋律
  5. ACM入门练习与递推小结
  6. Salesforce视图与控制器之间的交互
  7. Kali Linux 官方宣传视频
  8. 使用ffmpeg循环推流(循环读取视频文件)推送RTMP服务器的方法
  9. H264 Profile对比分析
  10. deepin--eclipse安装与配置