React 扩展
文章目录
- PureComponent
- 1. 使用 React.Component,不会进行浅比较
- 2. 使用 shouldComponentUpdate 生命周期钩子,手动比较
- 3. 使用 React.PureComponent,自动进行浅比较
- Render Props
- 1. 使用 Children props(通过组件标签体传入结构)
- 2. 使用 Render Props(通过组件标签属性传入结构)
- Error Boundaries(错误边界)
PureComponent
PureComponent 在其内部实现了 shouldComponentUpdate()
方法的浅比较逻辑。当组件的 props 或 state 发生变化时,React 会通过这个方法检查前后的 props 和 state 是否相等。
如果 shouldComponentUpdate()
返回 false,则 React 不会触发组件的重新渲染过程,这可以避免不必要的渲染和可能带来的性能开销。
1. 使用 React.Component,不会进行浅比较
当执行this.setState({})
时:
<Parent />组件
中 state 没有发生变化,也会重新执行render()
<Child />组件
没有接收任何props,也会重新执行render()
.
不管父子组件的 props 或 state 有没有发生变化,都会重新执行各自的render(),重新渲染组件。这显然不符合逻辑,效率低下
import React, { Component } from 'react'export default class Parent extends Component {state = { name: '张三' }changeName = () => {this.setState({})}render () {console.log('Parent render');return (<div><button onClick={this.changeName}>点击</button><Child /></div>)}
}class Child extends Component {render () {console.log('Child render');return (<div>Child</div>)}
}
.
2. 使用 shouldComponentUpdate 生命周期钩子,手动比较
使用 shouldComponentUpdate 生命周期钩子,手动判断 props 或 state 的发生变化:
- 如果父组件数据没有更新,则父组件和子组件都不需要重新render():
父组件 => shouldComponentUpdate () { return false }
- 如果父组件数据有更新,则父组件需要重新render():
父组件 => shouldComponentUpdate () { return true }
- 子组件则判断props数据有没有更新:
子组件 => shouldComponentUpdate (nextProps, nextState) { return !this.props.name === nextProps.name }
import React, { Component, PureComponent } from 'react'export default class Parent extends Component {state = { name: '张三' }changeName = () => {this.setState({})}shouldComponentUpdate (nextProps, nextState) {// 当执行 this.setState({})时,state中数据没有变化时, return false 阻止更新.这样就不会重新渲染Parent组件,Child组件也不会更新// 当执行 this.setState({ name: '李四' })时,state中数据发生改变, return true 这会重新渲染Parent组件,这是Child组件的props会改变if (this.state.name === nextState.name) {return false} else {return true}}render () {console.log('Parent render');return (<div><button onClick={this.changeName}>点击</button><Child name={this.state.name} /></div>)}
}class Child extends Component {// 如果接收到的props中数据没有变化,则return false,阻止组件更新shouldComponentUpdate (nextProps, nextState) {if (this.props.name === nextProps.name) {return false} else {return true}}render () {console.log('Child render');return (<div>Child{this.props.name}</div>)}
}
3. 使用 React.PureComponent,自动进行浅比较
PureComponent 在其内部实现了 shouldComponentUpdate()
方法的浅比较逻辑。当组件的 props 或 state 发生变化时,React 会通过这个方法检查前后的 props 和 state 是否相等。
import React, { PureComponent } from 'react'export default class Parent extends PureComponent {state = { name: '张三' }changeName = () => {this.setState({})}// 相当于PureComponent中内置shouldComponentUpdate的判断逻辑// shouldComponentUpdate (nextProps, nextState) {// return !this.state.name === nextState.name// }render () {console.log('Parent render');return (<div><button onClick={this.changeName}>点击</button><Child name={this.state.name} /></div>)}
}class Child extends PureComponent {// 相当于PureComponent中内置shouldComponentUpdate的判断逻辑// shouldComponentUpdate (nextProps, nextState) {// return !this.props.name === nextProps.name// }render () {console.log('Child render');return (<div>Child{this.props.name}</div>)}
}
Render Props
在React中,并没有直接对应于 Vue.js 中的 “插槽”(slot)的概念。Vue.js的插槽允许你在子组件的模板中预留一些占位符,这些占位符可以由父组件来填充内容。
然而,React通过其组合和props传递的特性,提供了类似的功能,但实现方式略有不同。
1. 使用 Children props(通过组件标签体传入结构)
在子组件中可以通过 this.props.children
接收并渲染父组件传递的任何内容
import React, { Component } from 'react'export default class Parent extends Component {state = { name: '张三' }render () {return (<Child><p>这是一段文本。</p><button>这是一个按钮。</button></Child>)}
}class Child extends Component {render () {return (<div className='childNode'>{/* 获取到<Child>中的标签属性 */}{this.props.children} // 这里可以接收并渲染父组件传递的任何内容</div>)}
}
把 <Child>
内部的两个节点插入到 .childNode
中
多层嵌套
-
通过
<Child> <Grand/> </Child>
的形式,形成父子组件 -
通过
{this.props.children}
的形式,渲染内容
import React, { Component } from 'react'// 父组件
export default class Parent extends Component {state = { name: '张三' }render () {return (<Child>{/* Grand是Child的子组件 */}<Grand name={this.state.name} /></Child>)}
}// 子组件
class Child extends Component {state = { name: '李四' }render () {return (<div className='childNode'><p>Child组件</p>{this.props.children}</div>)}
}// 孙子组件
class Grand extends Component {render () {return (<div className='grandNode'><p>Grand组件</p><p>{this.props.name}</p></div>)}
}
但这样 Child 组件
里的数据(state = { name: '李四' }
)无法传递给 Grand 组件
,因此需要使用 Render Props
.
2. 使用 Render Props(通过组件标签属性传入结构)
Render props是一种在React组件之间共享代码的模式。一个组件接收一个返回React元素的函数作为prop,并在其渲染方法中调用该函数。这使得父组件能够动态地决定子组件应该渲染什么内容。
-
通过
<Child render={() => <Grand />} />
的形式,形成父子组件:render prop
的模式来在Child 组件
中动态渲染Grand 组件
-
通过
{this.props.render()}
的形式,动态渲染内容
import React, { Component } from 'react'// 父组件
export default class Parent extends Component {state = { name: '张三' }render () {return (// 通过 render prop 的模式来在 Child 组件中动态渲染 Grand 组件<Child render={(name) => <Grand name={name} />} />)}
}// 子组件
class Child extends Component {state = { name: '李四' }render () {return (<div className='childNode'><p>Child组件</p>{/* <Grand>组件被放置在这里,并传入Child组件的数据(name: '李四') */}{/* 相当与vue中<slot>插槽,动态渲染的位置 */}{this.props.render(this.state.name)} </div>)}
}// 孙子组件
class Grand extends Component {render () {return (<div className='grandNode'><p>Grand组件</p><p>{this.props.name}</p></div>)}
}
这样 Child 组件
里的数据(state = { name: '李四' }
)就可以传递给 Grand 组件
了
Error Boundaries(错误边界)
正常情况下,子组件在任何位置的报错,都会使整个页面崩溃。
import React, { Component } from 'react'// 父组件
export default class Parent extends Component {render () {return (<div><h2>父组件Parent</h2><Child /></div>)}
}// 子组件
class Child extends Component {state = {list: '', // 会导致 this.state.list.map 报错,从而使整个页面崩溃// list: [// { id: 1, name: '张三' },// { id: 2, name: '李四' },// { id: 3, name: '王五' },// ]}render () {return (<ul>{this.state.list.map((item) => {return <li key={item.id}>{item.name}</li>})}</ul>)}
}
上例中,state.list=''
会导致 this.state.list.map
报错,从而使整个页面被摧毁。
.
使用 Error Boundaries 可以把错误被限定在指定的边界,并捕获错误信息,来确保单个错误或异常不会导致整个应用程序或页面崩溃。
在 React 中,Error Boundaries 是一种特殊的组件,可以捕获并打印发生在其子组件树任何位置的 JavaScript 错误,并且,它会阻止整个 React 组件树被这个错误摧毁。当错误被捕获后,Error Boundary 可以选择显示一个降级 UI 而不是崩溃的组件树,这允许用户可以继续使用应用的其他部分。
要使用 Error Boundaries,需要创建一个类组件,并在其中实现 static getDerivedStateFromError()
和 componentDidCatch()
这两个生命周期方法。
- static getDerivedStateFromError() : 当子组件出现报错时,会触发该回调,并携带错误信息
- componentDidCatch(): 渲染组件时出错会被调用,常用于统计错误信息并传给后台
注意:
- 只有生产环境才生效
- 只能捕获后代组件生命周期中抛出的错误,不能捕获自身组件产生的错误
- 不是生命周期的错误无法捕获
import React, { Component } from 'react'// 父组件
export default class Parent extends Component {state = {hasError: ''// 用于标识子组件是否产生错误}// 当Parent的子组件出现报错时,会触发getDerivedStateFromError调用,并携带错误信息static getDerivedStateFromError (error) {console.log('getDerivedStateFromError:', error);return { hasError: error } // 返回一个error状态,并更新state中的hasError}componentDidCatch (error, errorInfo) {console.log('渲染组件时出错会被调用');// 可以将错误日志上报给服务器 console.error("Caught an error in ErrorBoundary", error, errorInfo);// 还可以将错误信息存储在 state 中 // this.setState({ // error: error, // errorInfo: errorInfo // });}render () {return (<div><h2>父组件Parent</h2>{this.state.hasError ? <h2>子组件出错</h2> : <Child />}</div>)}
}// 子组件
class Child extends Component {state = {list: '',// list: [// { id: 1, name: '张三' },// { id: 2, name: '李四' },// { id: 3, name: '王五' },// ]}render () {return (<ul>{this.state.list.map((item) => {return <li key={item.id}>{item.name}</li>})}</ul>)}
}
父组件正常显示,报错的子组件则显示 <h2>子组件出错</h2>
相关文章:

React 扩展
文章目录 PureComponent1. 使用 React.Component,不会进行浅比较2. 使用 shouldComponentUpdate 生命周期钩子,手动比较3. 使用 React.PureComponent,自动进行浅比较 Render Props1. 使用 Children props(通过组件标签体传入结构&…...

IT入门知识第八部分《云计算》(8/10)
目录 云计算:现代技术的新篇章 1. 云计算基础 1.1 云计算的起源和发展 云计算的早期概念 云计算的发展历程 1.2 云计算的核心特点 按需自助服务 广泛的网络访问 资源池化 快速弹性 按使用量付费 1.3 云计算的优势和挑战 成本效益 灵活性和可扩展性 维…...

Linux-笔记 全志T113移植正点4.3寸RGB屏幕笔记
目录 前言 线序整理 软件 显示调试 触摸调试 背光调试 前言 由于手头有一块4.3寸的RGB屏幕(触摸IC为GT1151),正好开发板上也有40Pin的RGB接口,就想着给移植一下,前期准备工作主要是整理好线序,然后用转接板与杜邦线连接验证好…...

Linux shell编程学习笔记59: ps 获取系统进程信息,类似于Windows系统中的tasklist 命令
0 前言 系统进程信息是电脑网络信息安全检查中的一块重要内容,对于使用Linux和基于Linux作为操作系统的电脑来说,可以使用ps命令。 1 ps命令 的功能、格式和选项说明 1.1 ps命令 的功能 Linux 中的ps(意为:process status&…...

在Android中使用ProgressBar显示进度
在Android中使用ProgressBar显示进度 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将探讨如何在Android应用中使用ProgressBar来显示进度。ProgressB…...

Java基础面试题(简单版):
1.java的8个基本数据类型? 整型: byte(占用1个字节) short(占用2个字节) int(占用4个字节) long(占用8个字节) 浮点型: float(占用4个字节)、double(占用8个字节) 字符型: char 布尔型: boolean 2.ArrayList和LinkedList的区别? 可以说ArrayList和LinkedList除了是同属于集合…...

Chrome插件:Postman Interceptor 调试的终极利器
今天给大家介绍一款非常实用的工具——Postman Interceptor。 这个工具可以捕捉任何网站的请求,并将其发送到Postman客户端。 对于经常和API打交道的程序员来说,Postman Interceptor真的是神器级别的存在。 下面就让我详细说说这个插件怎么用…...

SpringBoot学习04-[定制SpringMVC]
定制SpringMVC 定制SpringMvc的自动配置定制springmvc-configurePathMatch配置定制SpringMVC-拦截器Interceptor定制SpringMVC-CORS配置全局cors配置针对某个方法加跨域解决 WebMvcConfigurer原理定制SpringMVC-JSONJSON开发jackson的使用定制化json序列化和反序列化 JSON国际化…...

QT拖放事件之六:自定义MIME类型的存储及读取demo
1、MIME类型描述 MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的标准,用来表示文档、文件或字节流的性质和格式。 MIME 消息能包含文本、图像、音频、视频以及其他应用程序专用的数据。 浏览器通常使用 MIME 类型(而不是文件扩展名)来确定如何处理URL…...

架构师必知的绝活-JVM调优
前言 为什么要学JVM? 首先:面试需要 了解JVM能帮助回答面试中的复杂问题。面试中涉及到的JVM相关问题层出不穷,难道每次面试都靠背几百上千条面试八股? 其次:基础知识决定上层建筑 自己写的代码都不知道是怎么回事&a…...

小米平板6系列对比
小米平板6系列目前有4款,分别为6、6 Pro、6 Max、6S Pro。具体对比如下表所示。 小米平板型号66 Pro6 Max6S Pro实物图发布时间2023年4月21日2023年4月21日2023年8月14日2024年2月22 日屏幕大小11英寸11英寸14英寸12.4英寸分辨率2.8K2.8K2.8K3K刷新率144Hz144Hz120…...

用 Rust 实现一个替代 WebSocket 的协议
很久之前我就对websocket颇有微词,它的确满足了很多情境下的需求,但是仍然有不少问题。对我来说,最大的一个问题是websocket的数据是明文传输的,这使得websocket的数据很容易遭到劫持和攻击。同时,WebSocket继承自HTTP…...

【docker】2. 编排容器技术发展史(了解)
该篇文章介绍的主要是编排以及容器技术的发展史(了解即可),如果想单纯学习docker命令操作可直接略过!!! 容器技术发展史 Jail 时代 容器不是一个新概念或者新技术,很早就有了,只是近几年遇到了云计算&am…...

吉利银河L6(官方小订送的3M) 对比 威固vk70+ks15
吉利送的号称价值2000的3M效果 撕膜重贴 威固vk70ks15 之后的效果 // 忘记测反射的热量了 可以验证金属膜是反射热而不是吸热 金属膜 手机GPS还能用吗 亲测 能用 太阳能总阻隔率 3M貌似20%出头 威固前档55% 侧后挡高一点不超过60% 夏天真实太阳发热能量 即阻隔率55%到60% …...

three.js实现雪花场景效果
点击获取雪花图片素材 提取码:lywa // 雪花效果 import * as THREE from "three" export function getsnowEffect(th) {console.log(th, th) // this 场景var that th// 创建一个BufferGeometry对象,用于存储顶点数据 const geometry new THREE.Buffe…...

鸿蒙 HarmonyOS NEXT星河版APP应用开发-阶段一
一、鸿蒙开发环境搭建 DevEco Studio安装 下载 访问官网:https://developer.huawei.com/consumer/cn/deveco-studio/选择操作系统版本后并注册登录华为账号既可下载安装包 安装 建议:软件和依赖安装目录不要使用中文字符软件安装包下载完成后࿰…...

Elasticsearch优化索引映射和设置
在Elasticsearch的世界中,优化索引的映射(mapping)和设置(settings)对于提高搜索性能、存储效率和系统稳定性至关重要。本文将带您深入了解如何针对Elasticsearch的索引进行优化,帮助您构建更高效、更可靠的…...

boss直聘招聘数据可视化分析
boss直聘招聘数据可视化分析 一、数据预处理二、数据可视化三、完整代码一、数据预处理 在 上一篇博客中,笔者已经详细介绍了使用selenium爬取南昌市web前端工程师的招聘岗位数据,数据格式如下: 这里主要对薪水列进行处理,为方便处理,将日薪和周薪的数据删除,将带有13薪…...

小程序人脸分析
公司的业务需求是用户在使用某个功能前,必须使用人脸识别,确保当前使用人是用户本人,防止某些功能乱用。后端用的是腾讯的人脸识别方案,这里只是前端的识别代码,保证人脸剧中,大小合适,有一个人…...

UML建模笔记
5个视图 设计。类,接口,对象如何协作。实现。组件,运行程序,文档关系。用例。用户功能期望。进程。并发与同步相关进程,线程。部署。部署到计算机。 建模目的 和客户共创追踪需求变更协同开发进度控制持续迭代测试生…...

初见SpringCloud ing
Consul 服务注册与发现 服务注册与发现 服务注册:微服务在启动时,会将自己的信息(如 IP 地址、端口、服务名称等)注册到 Consul。 服务发现:其他微服务可以通过 Consul 查询到已注册的服务,并通过这些信息…...

Python | Leetcode Python题解之第198题打家劫舍
题目: 题解: class Solution:def rob(self, nums: List[int]) -> int:if not nums:return 0size len(nums)if size 1:return nums[0]first, second nums[0], max(nums[0], nums[1])for i in range(2, size):first, second second, max(first nu…...

什么是中断?---STM32篇
目录 一,中断的概念 二,中断的意义 三,中断的优先级 四,中断的嵌套 如果一个高优先级的中断发生,它会立即打断当前正在处理的中断(如果其优先级较低),并首先处理这个高优…...

51单片机第1步_putchar()和_getkey()应用
没有开发板,没有烧录器,没有学习场所,如何学习写51单片机的程序?除了采用软件模拟仿真,没有更好的方法,因此,使用串口是学习的第一步。 1、_getkey ()函数 在C:\Keil\C51\LIB中有一个叫GETKEY…...

微信小程序中的地图的使用
微信小程序中的地图组件 是一个用于展示地图的组件,提供了丰富的功能和配置选项,可以实现定位、标记、路线规划等多种地图相关的交互。下面是对这个组件的详细介绍,包括属性、事件以及示例代码。 组件属性 基础属性 longitude: 地图中心的经…...

MySQL root密码丢失处理
没有记住MySQL数据库root用户默认密码(为初始化安装mysql时默认生成) 1)修改/etc/my.cnf文件,在[mysqld]的段中加上一句:skip-grant-tables 重启mysql服务 [root@localhost ~]# service mysqld restart 2)以无密码方式进入mysql: [root@localhost ~]# /usr/local/my…...

RabbitMQ中java实现队列和交换机的声明
java实现队列和交换机的声明 在之前我们都是基于RabbitMQ控制台来创建队列、交换机。但是在实际开发时,队列和交换机是程序员定义的,将来项目上线,又要交给运维去创建。那么程序员就需要把程序中运行的所有队列和交换机都写下来,…...

解决SPA(单页应用)首屏加载速度慢
SPA是目前流行的前端开发模式,相对于传统的多页面用户体验更好,操作更顺畅,开发效率也更高。但是SPA首屏加载速度慢一直是个致命的问题,由于SPA应用首次打开需要一次性加载大量的静态资源,这就导致了加载速度慢的问题&…...

ElementUI框架搭建及组件使用
前言: 当开始使用ElementUI框架来搭建网站或Web应用程序时,了解框架的基本结构和组件的使用是至关重要的。ElementUI是一个基于Vue.js的框架,提供了丰富的UI组件和工具,可以帮助开发人员快速构建现代化的用户界面。 在本文中,我…...

同三维T908转换器 SDI转DVI/HDMI/VGA/色差分量/AV转换器
同三维T908转换器 SDI转DVI/HDMI/VGA/色差分量/AV转换器 1路SDI进,1路DVI(可转HDMI/VGA/色差分量/AV)3.5音频1路SDI出,可以支持音频解嵌,也可把3.5音频加嵌转换输出,输出分辨率可调,支持图像翻转180度 一、产品简介 SDI转万能转…...