React中的纯组件

React提供了一种基于浅比较模式来确定是否应该重新渲染组件的类React.PureComponent,通常只需要继承React.PureComponent就可以定义一个纯组件。React.PureComponentReact.Component很相似,两者的区别在于React.Component并未实现shouldComponentUpdate(),而React.PureComponent中以浅层对比propstate的方式来实现了该函数。如果赋予React组件相同的propsstaterender()函数会渲染相同的内容,那么在某些情况下使用React.PureComponent可提高性能。

描述

首先我们来回顾下React组件执行重渲染re-render更新的时机,一般当一个组件的props属性或者state状态发生改变的时候,也就是父组件传递进来的props发生变化或者使用this.setState函数时,组件会进行重新渲染re-render。而在接受到新的props或者state到组件更新之间会执行其生命周期中的一个函数shouldComponentUpdate,当该函数返回true时才会进行重渲染,如果返回false则不会进行重渲染,在这里shouldComponentUpdate默认返回true,因此当组件遇到性能瓶颈的时候可以在shouldComponentUpdate中进行逻辑判断,来自定义组件是否需要重渲染。

我们可以稍微查看一下源码的实现,可以看到PureComponent是通过寄生组合继承的方式继承了Componentcommit id 0cf22a5

// master/packages/react/src/ReactBaseClasses.js line 123
// ...
function ComponentDummy() {}
ComponentDummy.prototype = Component.prototype; /**
* Convenience component with default shallow equality check for sCU.
*/
function PureComponent(props, context, updater) {
this.props = props;
this.context = context;
// If a component has string refs, we will assign a different object later.
this.refs = emptyObject;
this.updater = updater || ReactNoopUpdateQueue;
} const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());
pureComponentPrototype.constructor = PureComponent;
// Avoid an extra prototype jump for these methods.
Object.assign(pureComponentPrototype, Component.prototype);
pureComponentPrototype.isPureReactComponent = true;
// ...

同时在checkShouldComponentUpdate函数中有一段这样的逻辑,在函数名上就能看出是对传入的参数进行了一次浅比较,因此实际上PureReactComponent组件和ReactComponent组件的区别就是React.PureComponent中以浅层对比propstate的方式来实现了shouldComponentUpdate()函数。

// master/packages/react-reconciler/src/ReactFiberClassComponent.new.js line 334
// ...
if (ctor.prototype && ctor.prototype.isPureReactComponent) {
return (
!shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)
);
}
// ...

需要注意的是,React.PureComponent中的shouldComponentUpdate()仅作对象的浅层比较。如果对象中包含复杂的数据结构,则有可能因为无法检查深层的差别,产生错误的比对结果。仅在你的propsstate较为简单时才使用React.PureComponent,或者每次更新都使用新的对象,或者在深层数据结构发生变化时调用forceUpdate()来确保组件被正确地更新,你也可以考虑使用immutable对象加速嵌套数据的比较。此外React.PureComponent中的shouldComponentUpdate()将跳过所有子组件树的prop更新,因此需要确保所有子组件也都是纯的组件。

优点

  • shouldComponentUpdate生命周期做了优化会自动shadow diff组件的stateprops,结合immutable数据就可以很好地去做更新判断。
  • 隔离了父组件与子组件的状态变化。

缺点

  • shouldComponentUpdate中的shadow diff同样消耗性能。
  • 需要确保组件渲染仅取决于propsstate

每日一题

https://github.com/WindrunnerMax/EveryDay

参考

https://zhuanlan.zhihu.com/p/30659051
https://juejin.cn/post/6844903618848669709
https://juejin.cn/post/6844904099679305741
https://segmentfault.com/a/1190000014979065
https://ginnko.github.io/2018/12/17/pure-component/
https://zh-hans.reactjs.org/docs/react-api.html#reactpurecomponent

React中的纯组件的更多相关文章

  1. React 中的 定义组件的 两种方式

    React 中创建 Components 的方式有两种:Function and Class 定义一个组件最简单的方法就是写一个 JavaScript 函数 function Welcome(prop ...

  2. react中使用截图组件Cropper组件

    --最近项目用react,学习react并使用cropper组件裁剪图片. (这里开发组件不够统一有用tsx(TypeScript + xml/html)写的组件,有用jsx(javascript+x ...

  3. React中的通讯组件

    1.父传子:     传递:当子组件在父组件中当做标签使用的时候,给当前子组件绑定一个自定义属性,值为需要传递的数据     接收:在子组件内部通过this.props进行接收 2.子传父     传 ...

  4. React中实现keepalive组件缓存效果

    背景:由于react官方并没有提供缓存组件相关的api(类似vue中的keepalive),在某些场景,会使得页面交互性变的很差,比如在有搜索条件的表格页面,点击某一条数据跳转到详情页面,再返回表格页 ...

  5. React中的固定组件(随遇随记)

    <React.StrictMode></React.StrictMode>对组件中使用严格模式 <React.Fragment></React.Fragmen ...

  6. React中的高阶组件

    高阶组件(HOC, High-Order Component)是React中用于重组组件逻辑的高级技术,是一种编程模式而不是React的api. 直观来讲,高阶组件是以某一组件作为参数返回一个新组件的 ...

  7. 前端笔记之React(二)组件内部State&React实战&表单元素的受控

    一.组件内部的State 1.1 state state叫状态,是每一个类式组件都有的属性,但函数式组件,没有state. state是一个对象,什么值都可以定义. 在任何类式组件的构造函数中,可以用 ...

  8. 初学React:定义一个组件

    接着聊React,今天说说如何创建一个组件类. <!DOCTYPE html> <html lang="en"> <head> <meta ...

  9. 从 Vue 的视角学 React(四)—— 组件传参

    组件化开发的时候,参数传递是非常关键的环节 哪些参数放在组件内部管理,哪些参数由父组件传入,哪些状态需要反馈给父组件,都需要在设计组件的时候想清楚 但实现这些交互的基础,是明白组件之间参数传递的方式, ...

  10. React中的Ajax

    React中的Ajax 组件的数据来源,通常是通过Ajax请求从服务器获取,可以使用componentDidMount方法设置Ajax请求,等到请求成功,再用this.setState方法重新渲染UI ...

随机推荐

  1. Ubuntu 安装 MinIO

    MinIO是一个开源的高性能对象存储解决方案,支持多种安装方式,本例仅介绍最基础的单机安装方式. 下载安装文件 直接从MinIO官网下载安装文件. 下载服务端 wget https://dl.min. ...

  2. Java中有哪些方式能实现锁某个变量

    有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 系列文章地址 在Java中,有几种方式可以实现对某个变量的锁定 ...

  3. [转帖]深入浅出分析LSM树(日志结构合并树)

    https://zhuanlan.zhihu.com/p/415799237 ​ 目录 收起 零.前言 一.LSM树数据结构定义 二.插入操作 三.删除操作 四.修改操作 五.查询操作 六.合并操作 ...

  4. [转帖]Fluentd 的优缺点

    https://zhuanlan.zhihu.com/p/129375187   以前在不少场合浅度使用过 Fluentd,将日志汇聚到一个地方.它给我的大体印象是 简单且能解决问题 直到最近遇到一个 ...

  5. [转帖]AMD Zen CPU 架构以及不同CPU性能大PK

    https://plantegg.github.io/2021/08/13/AMD_Zen_CPU%E6%9E%B6%E6%9E%84/ 前言 本文先介绍AMD Zen 架构,结合前一篇文章<C ...

  6. [转帖]BF16 与 FP16 在模型上哪个精度更高呢

    https://zhuanlan.zhihu.com/p/449345588 BF16 是对FP32单精度浮点数截断数据,即用8bit 表示指数,7bit 表示小数. FP16半精度浮点数,用5bit ...

  7. [转帖]美国出口管制条例(EAR)简介

    https://zhuanlan.zhihu.com/p/87962305 第一节.美国出口管制法律体系 下述一系列法律.法规及规则,构成美国完整的出口管理制度,是美国各相关执法部门执法的主要法律依据 ...

  8. [转帖]Linux命令拾遗-top中的%nice是啥

    https://www.cnblogs.com/codelogs/p/16060663.html 简介# 这是Linux命令拾遗系列的第八篇,本篇主要介绍top命令中nice%这个指标的含义以及进程优 ...

  9. IPV6的简单学习与整理

    背景 大概2018年时曾经突击学习过一段时间IPV6 当时没太有写文档的习惯,导致这边没有成型的记录了. 今天又有项目要求使用IPV6, 想了想就将之前学习的部分 还有想继续学习提高的部分进行一下总结 ...

  10. MYSQL 日志参数与性能的关系

    1. 先看一下mysql技术内幕 innodb存储引擎的一个结果 以及各个参数的含义