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. K8s集群CoreDNS监控告警最佳实践

    本文分享自华为云社区<K8s集群CoreDNS监控告警最佳实践>,作者:可以交个朋友. 一 背景 coreDNS作为K8s集群中的关键组成部分.主要负责k8s集群中的服务发现,域名解析等功 ...

  2. [转帖]Linux下非oracle用户如何使用系统认证方式登陆数据

    https://www.cnblogs.com/kerrycode/p/17772866.html Linux系统中,DBA一般使用oracle用户登陆/访问Linux操作系统,然后使用sqlplus ...

  3. [转帖]20--Deployment常规操作

    https://www.cnblogs.com/caodan01/p/15309966.html 目录 一.Deployment滚动更新 1.更新配置清单 2.设置镜像 kubectl set ima ...

  4. [转帖]Linux-计算毫秒数

    https://www.cnblogs.com/yeyuzhuanjia/p/15822653.html date +%s返回自划时代以来的秒数. date +%s%N返回秒数+当前纳秒数. 因此,e ...

  5. 关于sar的学习

    关于sar的学习 背景 公司一套基于某冷门Python架构的系统前几天出现异常卡顿. 当时安装的时候必须使用ubuntu系统. 所以当时默认安装的ubuntu1804, 本来想尝试使用一下sar查看卡 ...

  6. 【转帖】Linux性能优化(十三)——CPU性能测试

    一.CPU上下文切换测试场景 使用sysbench模拟多线程调度: sysbench --threads=10 --time=300 threads run 使用vmstat查看CPU上下文切换: c ...

  7. [转帖]Springboot配置https访问

    https://www.cnblogs.com/feifuzeng/p/14709372.html 介绍 该篇博文主要介绍如何配置Springboot使其打包部署的服务必须通过HTTPS协议才可访问, ...

  8. 使用TFS CI 又想保留服务运行状态的简单方法

    最近公司使用TFS-CI的方式定期部署测试环境, 但是发现TFS-CI 运行完之后会清理agent所在的测试环境. 运行的进程都会被killed 1. 第一种方法: 本来第一反应 是使用systemd ...

  9. 【JS 逆向百例】网洛者反爬练习平台第六题:JS 加密,环境模拟检测

    关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后 ...

  10. TienChin-课程管理-课程更新接口

    更改包名 将之前的 entity 更改为 domain: 将之前的 validator 包当中的校验分组接口移动到 common 模块当中,因为其它模块也需要使用就放到公共当中进行存储. 更改完毕之后 ...