React中的纯组件
React中的纯组件
React提供了一种基于浅比较模式来确定是否应该重新渲染组件的类React.PureComponent,通常只需要继承React.PureComponent就可以定义一个纯组件。React.PureComponent与React.Component很相似,两者的区别在于React.Component并未实现shouldComponentUpdate(),而React.PureComponent中以浅层对比prop和state的方式来实现了该函数。如果赋予React组件相同的props和state,render()函数会渲染相同的内容,那么在某些情况下使用React.PureComponent可提高性能。
描述
首先我们来回顾下React组件执行重渲染re-render更新的时机,一般当一个组件的props属性或者state状态发生改变的时候,也就是父组件传递进来的props发生变化或者使用this.setState函数时,组件会进行重新渲染re-render。而在接受到新的props或者state到组件更新之间会执行其生命周期中的一个函数shouldComponentUpdate,当该函数返回true时才会进行重渲染,如果返回false则不会进行重渲染,在这里shouldComponentUpdate默认返回true,因此当组件遇到性能瓶颈的时候可以在shouldComponentUpdate中进行逻辑判断,来自定义组件是否需要重渲染。
我们可以稍微查看一下源码的实现,可以看到PureComponent是通过寄生组合继承的方式继承了Component,commit 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中以浅层对比prop和state的方式来实现了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()仅作对象的浅层比较。如果对象中包含复杂的数据结构,则有可能因为无法检查深层的差别,产生错误的比对结果。仅在你的props和state较为简单时才使用React.PureComponent,或者每次更新都使用新的对象,或者在深层数据结构发生变化时调用forceUpdate()来确保组件被正确地更新,你也可以考虑使用immutable对象加速嵌套数据的比较。此外React.PureComponent中的shouldComponentUpdate()将跳过所有子组件树的prop更新,因此需要确保所有子组件也都是纯的组件。
优点
- 在
shouldComponentUpdate生命周期做了优化会自动shadow diff组件的state和props,结合immutable数据就可以很好地去做更新判断。 - 隔离了父组件与子组件的状态变化。
缺点
shouldComponentUpdate中的shadow diff同样消耗性能。- 需要确保组件渲染仅取决于
props与state。
每日一题
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中的纯组件的更多相关文章
- React 中的 定义组件的 两种方式
React 中创建 Components 的方式有两种:Function and Class 定义一个组件最简单的方法就是写一个 JavaScript 函数 function Welcome(prop ...
- react中使用截图组件Cropper组件
--最近项目用react,学习react并使用cropper组件裁剪图片. (这里开发组件不够统一有用tsx(TypeScript + xml/html)写的组件,有用jsx(javascript+x ...
- React中的通讯组件
1.父传子: 传递:当子组件在父组件中当做标签使用的时候,给当前子组件绑定一个自定义属性,值为需要传递的数据 接收:在子组件内部通过this.props进行接收 2.子传父 传 ...
- React中实现keepalive组件缓存效果
背景:由于react官方并没有提供缓存组件相关的api(类似vue中的keepalive),在某些场景,会使得页面交互性变的很差,比如在有搜索条件的表格页面,点击某一条数据跳转到详情页面,再返回表格页 ...
- React中的固定组件(随遇随记)
<React.StrictMode></React.StrictMode>对组件中使用严格模式 <React.Fragment></React.Fragmen ...
- React中的高阶组件
高阶组件(HOC, High-Order Component)是React中用于重组组件逻辑的高级技术,是一种编程模式而不是React的api. 直观来讲,高阶组件是以某一组件作为参数返回一个新组件的 ...
- 前端笔记之React(二)组件内部State&React实战&表单元素的受控
一.组件内部的State 1.1 state state叫状态,是每一个类式组件都有的属性,但函数式组件,没有state. state是一个对象,什么值都可以定义. 在任何类式组件的构造函数中,可以用 ...
- 初学React:定义一个组件
接着聊React,今天说说如何创建一个组件类. <!DOCTYPE html> <html lang="en"> <head> <meta ...
- 从 Vue 的视角学 React(四)—— 组件传参
组件化开发的时候,参数传递是非常关键的环节 哪些参数放在组件内部管理,哪些参数由父组件传入,哪些状态需要反馈给父组件,都需要在设计组件的时候想清楚 但实现这些交互的基础,是明白组件之间参数传递的方式, ...
- React中的Ajax
React中的Ajax 组件的数据来源,通常是通过Ajax请求从服务器获取,可以使用componentDidMount方法设置Ajax请求,等到请求成功,再用this.setState方法重新渲染UI ...
随机推荐
- DDP运行报错(单卡无错):ERROR:torch.distributed.elastic.multiprocessing.api:failed (exitcode: 1)
使用DDP时出现错误,但是单卡跑无错误. 错误记录如下: RuntimeError: Expected to have finished reduction in the prior iteratio ...
- 【Spring 5核心原理】1设计模式
1.1开闭原则 开闭原则(open-closed principle,OCP)是指一个软件实体(如类,模块和函数)应该对扩展开放,对修改关闭.所谓的开闭,也正是对扩展和修改两个行为的一个原则. 强调用 ...
- 持续集成指南:Gitlab CI/CD 自动部署前端项目
前言 之前陆续写了 Gitlab 的安装使用还有 Gitlab CI/CD 的配置使用,已经把 AspNetCore 的后端项目都做了持续集成了,尝到甜头之后,现在前端的项目也要加入自动化部署,所以经 ...
- [转帖]Linux内存之Cache
一. Linux内存之Cache 1.1.Cache 1.1.1.什么是Cache? Cache存储器,是位于CPU和主存储器DRAM之间的一块高速缓冲存储器,规模较小,但是速度很快,通常由SRAM( ...
- [转帖]ERROR 2068 (HY000): LOAD DATA LOCAL INFILE file request rejected due to restrictions on access.
1.报错信息 ERROR 2068 (HY000): LOAD DATA LOCAL INFILE file request rejected due to restrictions on acces ...
- [转帖]关于虚拟化中cpu的指令集SSE 4.2的不支持
背景: 局域网中有两台服务器proxmox进行了虚拟化,跑一些测试应用.今天正好想要安装一下clickhouse跑一下.安装前准备: 测试服务器是否支持sse 4.2指令集-如下 [root@slav ...
- [转帖]金仓数据库KingbaseES V8R6索引坏块故障处理
案例说明: 在执行表数据查询时,出现下图所示错误,索引故障导致表无法访问,后重建索引问题解决.本案例复现了此类故障解决过程. 适用版本: KingbaseES V8R3/R6 一.创建测试环境 # 表 ...
- [转帖]016 Linux 卧槽,看懂进程信息也不难嘛?top、ps
016 Linux 卧槽,看懂进程信息也不难嘛?top.pshttps://my.oschina.net/u/3113381/blog/5455267 1 扒开看看 top 命令参数详情 Linux ...
- NextJs 与 Tailwind 入门开发笔记
前言 距离上次更新已经过去好久了,之前我在 StarBlog 博客2023年底更新一览的文章里说要使用 Next.js 来重构博客前端,最近也确实用 next.js 做了两个小项目,一个是单点认证项目 ...
- 从零开始配置 vim(6)——缩写
关于vim能快速编辑文本的能力,我们见识到了 operator + motion ,见识到了. 范式和宏.甚至可以使用命令来加快文本编辑.在后面我们又介绍了快捷键绑定来快速执行我们想要的操作.今天我们 ...