react组件进阶(四)
文章目录
- 1. 组件通讯介绍
- 2. 组件的 props
- 3. 组件通讯的三种方式
- 3.1 父组件传递数据给子组件
- 3.2 子组件传递数据给父组件
- 3.3 兄弟组件
- 4. Context
- 5. props 深入
- 5.1 children 属性
- 5.2 props 校验
- 5.3 props 的默认值
- 6. 组件的生命周期
- 6.1 组件的生命周期概述
- 6.2 生命周期的三个阶段
- 6.3 不常用钩子函数介绍
- 7. render-props和高阶组件
- 7.1 React组件复用概述
- 7.2 render props 模式
- 7.3 高阶组件
- 总结:
1. 组件通讯介绍
组件是独立且封闭的单元,默认情况下,只能使用组件自己的数据。在组件化过程中,我们将一个完整的功能
拆分成多个组件,以更好的完成整个应用的功能。而在这个过程中,多个组件之间不可避免的要共享某些数据
。为了实现这些功能,就需要打破组件的独立封闭性,让其与外界沟通。这个过程就是 组件通讯。
2. 组件的 props
- 组件是封闭的,要接收外部数据应该通过 props 来实现
- props的作用:接收传递给组件的数据
- 传递数据:给组件标签添加属性
- 接收数据:函数组件通过参数props接收数据,类组件通过 this.props 接收数据
特点
- 可以给组件传递任意类型的数据
- props 是只读的对象,只能读取属性的值,无法修改对象
- 注意:使用类组件时,如果写了构造函数,应该将 props 传递给 super() ,否则,无法在构造函数中获取到 props!
class Hello extends React.Component {constructor(props) {// 推荐将props传递给父类构造函数super(props)
}
render() {return <div>接收到的数据:{this.props.age}</div>
}
}
3. 组件通讯的三种方式
组件之间的通讯分为 3 种:
1.父组件 -> 子组件
2.子组件 -> 父组件
3.兄弟组件
3.1 父组件传递数据给子组件
- 父组件提供要传递的state数据
- 给子组件标签添加属性,值为 state 中的数据
- 子组件中通过 props 接收父组件中传递的数据
class Parent extends React.Component {state = { lastName: '王' }render() {return (<div>传递数据给子组件:<Child name={this.state.lastName} /> </div>)}
}
function Child(props) {return <div>子组件接收到数据:{props.name}</div>
}
3.2 子组件传递数据给父组件
思路:利用回调函数,父组件提供回调,子组件调用,将要传递的数据作为回调函数的参数。
- 父组件提供一个回调函数(用于接收数据)
- 将该函数作为属性的值,传递给子组件
class Parent extends React.Component {getChildMsg = (msg) => {console.log('接收到子组件数据', msg)}render() {return (<div>子组件:<Child getMsg={this.getChildMsg} /></div>)}
}
- 子组件通过 props 调用回调函数
- 将子组件的数据作为参数传递给回调函数
class Child extends React.Component {state = { childMsg: 'React' }handleClick = () => {this.props.getMsg(this.state.childMsg) }return (<button onClick={this.handleClick}>点我,给父组件传递数据</button> )
}
注意:回调函数中 this 指向问题!
3.3 兄弟组件
- 将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态
- 思想:状态提升
- 公共父组件职责:1. 提供共享状态 2. 提供操作共享状态的方法
- 要通讯的子组件只需通过 props 接收状态或操作状态的方法
4. Context
思考:App 组件要传递数据给 Child 组件,该如何处理?
- 处理方式:使用 props 一层层组件往下传递(繁琐)
思考:App 组件要传递数据给 Child 组件,该如何处理?
- 更好的姿势:使用 Context
- 作用:跨组件传递数据(比如:主题、语言等)
使用步骤:
1.调用 React. createContext() 创建 Provider (提供数据) 和 Consumer(消费数据) 两个组件。
const { Provider, Consumer } = React.createContext()
2.使用 Provider 组件作为父节点。
<Provider><div className="App"><Child1 /></div>
</Provider>
3.设置 value 属性,表示要传递的数据。
<Provider value="pink">
4.调用 Consumer 组件接收数据。
<Consumer>{data => <span>data参数表示接收到的数据 -- {data}</span>}
</Consumer>
总结:
- 如果两个组件是远方亲戚(比如,嵌套多层)可以使用Context实现组件通讯
- Context提供了两个组件:Provider 和 Consumer
- Provider组件:用来提供数据
- Consumer组件:用来消费数据
5. props 深入
5.1 children 属性
- children 属性:表示组件标签的子节点。当组件标签有子节点时, props 就会有该属性
- children 属性与普通的props一样,值可以是任意值(文本、React元素、组件,甚至是函数)
function Hello(props) {return (<div>组件的子节点:{props.children}</div>)
}
<Hello>我是子节点</Hello>
5.2 props 校验
- 对于组件来说,props 是外来的,无法保证组件使用者传入什么格式的数据
- 如果传入的数据格式不对,可能会导致组件内部报错
- 关键问题:组件的使用者不知道明确的错误原因
// 小明创建的组件App
function App(props) {const arr = props.colorsconst lis = arr.map((item, index) => <li key={index}>{item.name}</li>) return (<ul>{lis}</ul>)
}// 小红使用组件App
<App colors={19} />
- props 校验:允许在创建组件的时候,就指定 props 的类型、格式等
- 作用:捕获使用组件时因为props导致的错误,给出明确的错误提示,增加组件的健壮性
App.propTypes = {colors: PropTypes.array
}
使用步骤
- 安装包 prop-types (yarn add prop-types / npm i props-types)
- 导入 prop-types 包
- 使用组件名. propTypes = {} 来给组件的props添加校验规则
- 校验规则通过 PropTypes 对象来指定
import PropTypes from 'prop-types'
function App(props) {return (<h1>Hi, {props.colors}</h1>)
}
App.propTypes = {// 约定colors属性为array类型// 如果类型不对,则报出明确错误,便于分析错误原因 colors: PropTypes.array
}
约束规则
- 常见类型:array、bool、func、number、object、string
- React元素类型:element
- 必填项:isRequired
- 特定结构的对象:shape({ })
// 常见类型
optionalFunc: PropTypes.func,
// 必选
requiredFunc: PropTypes.func.isRequired,
// 特定结构的对象
optionalObjectWithShape: PropTypes.shape({color: PropTypes.string,fontSize: PropTypes.number
})
5.3 props 的默认值
- 场景:分页组件 每页显示条数
- 作用:给 props 设置默认值,在未传入 props 时生效
function App(props) {return (<div>此处展示props的默认值:{props.pageSize}</div>)
}
// 设置默认值
App.defaultProps = {pageSize: 10
}
// 不传入pageSize属性
<App />
6. 组件的生命周期
6.1 组件的生命周期概述
- 意义:组件的生命周期有助于理解组件的运行方式、完成更复杂的组件功能、分析组件错误原因等 组件的生命周期:组件从被创建到挂载到页面中运行,再到组件不用时卸载的过程
- 生命周期的每个阶段总是伴随着一些方法调用,这些方法就是生命周期的钩子函数。
- 钩子函数的作用:为开发人员在不同阶段操作组件提供了时机。
- 只有 类组件 才有生命周期。
6.2 生命周期的三个阶段
- 每个阶段的执行时机
- 每个阶段钩子函数的执行顺序
- 每个阶段钩子函数的作用
1.创建时(挂载阶段)
- 执行时机:组件创建时(页面加载时)
- 执行顺序:
- 更新时(更新阶段)
- 执行时机:1. setState() 2. forceUpdate() 3. 组件接收到新的props
- 说明:以上三者任意一种变化,组件就会重新渲染
- 执行顺序:
- 卸载时(卸载阶段)
- 执行时机:组件从页面中消失
6.3 不常用钩子函数介绍
旧版生命周期钩子函数(知道):
新版完整生命周期钩子函数(知道):
7. render-props和高阶组件
7.1 React组件复用概述
- 思考:如果两个组件中的部分功能相似或相同,该如何处理?
- 处理方式:复用相似的功能(联想函数封装)
- 复用什么?1. state 2. 操作state的方法 (组件状态逻辑 )
- 两种方式:1. render props 模式 2. 高阶组件(HOC)
- 注意:这两种方式不是新的API,而是利用React自身特点的编码技巧,演化而成的固定模式(写法)
7.2 render props 模式
思路分析
- 思路:将要复用的state和操作state的方法封装到一个组件中
- 问题1:如何拿到该组件中复用的state?
- 在使用组件时,添加一个值为函数的prop,通过 函数参数 来获取(需要组件内部实现)
<Mouse render={(mouse) => {}}/>
<Mouse render={(mouse) => (
<p>鼠标当前位置 {mouse.x},
{mouse.y}</p> )}/>
使用步骤
- 创建Mouse组件,在组件中提供复用的状态逻辑代码(1. 状态 2. 操作状态的方法)
- 将要复用的状态作为 props.render(state ) 方法的参数,暴露到组件外部
- 使用 props.render() 的返回值作为要渲染的内容
class Mouse extends React.Component { // … 省略state和操作state的方法 render() {return this.props.render(this.state) }
}
<Mouse render={(mouse) => <p>鼠标当前位置 {mouse.x},{mouse.y}</p>}/>
演示Mouse组件的复用
- Mouse组件负责:封装复用的状态逻辑代码(1. 状态 2. 操作状态的方法)
- 状态:鼠标坐标(x, y)
- 操作状态的方法:鼠标移动事件
- 传入的render prop负责:使用复用的状态来渲染UI结构
class Mouse extends React.Component { // … 省略state和操作state的方法 render() {return this.props.render(this.state) }
}
<Mouse render={(mouse) => <p>鼠标当前位置 {mouse.x},{mouse.y}</p>}/>
children代替render 属性
- 注意:并不是该模式叫 render props 就必须使用名为render的prop,实际上可以使用任意名称的prop
- 把prop是一个函数并且告诉组件要渲染什么内容的技术叫做:render props模式
- 推荐:使用 children 代替 render 属性
<Mouse>{({x, y}) => <p>鼠标的位置是 {x},{y}</p> }
</Mouse>
// 组件内部:
this.props.children(this.state)
// Context 中的用法:
<Consumer>{data => <span>data参数表示接收到的数据 -- {data}</span>}
</Consumer>
代码优化
1.推荐:给 render props 模式添加 props校验
2.应该在组件卸载时解除 mousemove 事件绑定
Mouse.propTypes = {chidlren: PropTypes.func.isRequired
}
componentWillUnmount() {window.removeEventListener('mousemove', this.handleMouseMove)
}
7.3 高阶组件
概述
- 目的:实现状态逻辑复用
- 采用 包装(装饰)模式 ,比如说:手机壳
- 手机:获取保护功能
- 手机壳 :提供保护功能
- 高阶组件就相当于手机壳,通过包装组件,增强组件功能
思路分析
- 高阶组件(HOC,Higher-Order Component)是一个函数,接收要包装的组件,返回增强后的组件
- 高阶组件内部创建一个类组件,在这个类组件中提供复用的状态逻辑代码,通过prop将复用的状态传递给
被包装组件 WrappedComponent
const EnhancedComponent = withHOC(WrappedComponent)
// 高阶组件内部创建的类组件:
class Mouse extends React.Component {render() {return <WrappedComponent {...this.state} />}
}
使用步骤
- 创建一个函数,名称约定以 with 开头
- 指定函数参数,参数应该以大写字母开头(作为要渲染的组件)
function withMouse() {}function withMouse(WrappedComponent) {}
- 在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回
- 在该组件中,渲染参数组件,同时将状态通过prop传递给参数组件
function withMouse(WrappedComponent) { class Mouse extends React.Component {} return Mouse
}
// Mouse组件的render方法中:
return <WrappedComponent {...this.state} />
使用步骤
1.创建一个函数,名称约定以 with 开头
2.指定函数参数,参数应该以大写字母开头(作为要渲染的组件)
3.在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回
4.在该组件中,渲染参数组件,同时将状态通过prop传递给参数组件
5.调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中
// 创建组件
const MousePosition = withMouse(Position) // 渲染组件
<MousePosition />
设置displayName
- 使用高阶组件存在的问题:得到的两个组件名称相同
- 原因:默认情况下,React使用组件名称作为 displayName
- 解决方式:为 高阶组件 设置 displayName 便于调试时区分不同的组件
- displayName的作用:用于设置调试信息(React Developer Tools信息)
设置方式:
Mouse.displayName = `WithMouse${getDisplayName(WrappedComponent)}` function getDisplayName(WrappedComponent) {return WrappedComponent.displayName || WrappedComponent.name ||
'Component' }
传递props
- 问题:props丢失
- 原因:高阶组件没有往下传递props
- 解决方式:渲染 WrappedComponent 时,将 state 和 this.props 一起传递给组件
- 传递方式:
<WrappedComponent {...this.state} {...this.props} />
总结:
React 组件进阶
1.组件通讯是构建 React 应用必不可少的一环。
2.props 的灵活性让组件更加强大。
3.状态提升是R eact组件的常用模式。
4.组件生命周期有助于理解组件的运行过程。
5.钩子函数让开发者可以在特定的时机执行某些功能。
6.render props模式和高阶组件都可以实现组件状态逻辑复用。
7.组件极简模型: (state, props) => UI
相关文章:

react组件进阶(四)
文章目录1. 组件通讯介绍2. 组件的 props3. 组件通讯的三种方式3.1 父组件传递数据给子组件3.2 子组件传递数据给父组件3.3 兄弟组件4. Context5. props 深入5.1 children 属性5.2 props 校验5.3 props 的默认值6. 组件的生命周期6.1 组件的生命周期概述6.2 生命周期的三个阶段…...

阿维塔城区NCA智驾导航辅助,复杂路口,全面胜任
阿维塔11城区NCA智驾导航辅助将于3月在上海、深圳等城市分阶段开启体验,以看得清、判得准、控得稳的“智驾”,进一步巩固业界智能天花板的地位。智能驾驶里程碑,拨杆两下开启都市安适旅程作为AVATRANS智能领航系统的重要组成部分,…...

[Pandas] div()函数
div()方法将DataFrame中的每个值除以指定的值,并返回一个计算处理后的Dataframe结果 DataFrame.div()函数其实是除法运算,表格中的每个数据都是被除数 导入数据 import pandas as pd df pd.DataFrame({"col1":[5, 3, None, 4], "col2…...
c++并发与多线程
c并发与多线程 子线程结束,主线程不能结束,否则会出错,和java不一样。 可以用join的方式让主线程等待子线程执行结束。 quickStart 线程相关头文件 #include <thread> 使用全局函数构造一个线程对象 #include <iostream> #…...

Vinylsulfone PEG Biotin,Biotin-PEG-VS,生物素聚乙二醇乙烯砜,VS基团容易与游离巯基发生反应
●中文名:乙烯砜PEG生物素,生物素聚乙二醇乙烯砜 ●英文名:Vinylsulfone PEG Biotin, VS-PEG-Biotin,Vinyl sulfone-PEG-Biotin,Biotins-PEG-sulfone Vinyl●产品理化指标: CAS号:N/A 分子量&am…...

论文学习——Tune-A-Video
Tune-A-Video: One-Shot Tuning of Image Diffusion Models for Text-to-Video Generation Abstract 本文提出了一种方法,站在巨人的肩膀上——在大规模图像数据集上pretrain并表现良好的 text to image 生成模型——加入新结构并进行微调,训练出一套 …...

C++类与对象part1
目录 1.类的6个默认函数 2.构造函数(相当于init) 3.析构函数 (相当于destroy) 4.拷贝构造函数 赋值运算符重载 运算符重载 赋值运算符重载 引入: 你知道为什么cout可以自动识别类型吗? 其实cout是一…...
记一次抓取网页内容
已打码 // UserScript // name --------- // namespace http://tampermonkey.net/ // version 0.1 // description https://---------oups/{id}/topics?scopeall&count20&begin_time2022-09-01T00%3A00%3A00.000%2B0800&end_time2022-10-01T00%…...

parasoft帮助史密斯医疗通过测试驱动开发提供安全、高质量的医疗设备
parasoft是一家专门提供软件测试解决方案的公司,Parasoft通过其经过市场验证的自动化软件测试工具集成套件,帮助企业持续交付高质量的软件。Parasoft的技术支持嵌入式、企业和物联网市场,通过将静态代码分析和单元测试、Web UI和API测试等所有…...

SpringBoot整合Oauth2开放平台接口授权案例
<!-- SpringBoot整合Web组件 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId>&l…...
Linux_创建用户
创建一个名为hello的用户,并指定/home/hello为根目录useradd -d /home/hello -m hello 设置密码 ,密码会输入两次,一次设置密码,一次确认密码,两次密码要输入的一样passwd hellouseradd的常用参数含义-d指定用户登入时的主目录&am…...

RDD(弹性分布式数据集)总结
文章目录一、设计背景二、RDD概念三、RDD特性四、RDD之间的依赖关系五、阶段的划分六、RDD运行过程七、RDD的实现一、设计背景 1.某些应用场景中,不同计算阶段之间会重用中间结果,即一个阶段的输出结果会作为下一个阶段的输入。如:迭代式算法…...

服务器版RstudioServer安装与配置详细教程
Docker部署Rstudio server 背景:如果您想在服务器上运行RstudioServer,可以按照如下方法进行操作,笔者测试时使用腾讯云服务器(系统centos7),需要在管理员权限下运行 Rstudio 官方提供了使用不同 R 版本的 …...
如何在Java中将一个列表拆分为多个较小的列表
在Java中,有多种方法可以将一个列表拆分为多个较小的列表。在本文中,我们将介绍三种不同的方法来实现这一目标。 方法一:使用List.subList()方法 List接口提供了一个subList()方法,它可以用来获取列表中的一部分元素。我们可以使…...

TryHackMe-Inferno(boot2root)
Inferno 现实生活中的机器CTF。该机器被设计为现实生活(也许不是?),非常适合刚开始渗透测试的新手 “在我们人生旅程的中途,我发现自己身处一片黑暗的森林中,因为直截了当的道路已经迷失了。我啊…...
微信原生开发中 JSON配置文件的作用 小程序中有几种JSON配制文件
关于json json是一种数据格式,在实际开发中,JSON总是以配制文件的形式出现,小程序与不例外,可对项目进行不同级别的配制。Q:小程序中有几种配制文件A:小程序中有四种配制文件分别是:project.config.json si…...
【python】为什么使用python Django开发网站这么火?
关注“测试开发自动化” 弓中皓,获取更多学习内容) Django 是一个基于 Python 的 Web 开发框架,它提供了许多工具和功能,使开发者可以更快地构建 Web 应用程序。以下是 Django 开发中的一些重要知识点: MTV 模式&#…...

Java设计模式(五)—— 责任链模式
责任链模式定义如下:使多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,知道有一个对象处理它为止。 适合使用责任链模式的情景如下: 有许多对…...
VMLogin:虚拟浏览器提供的那些亮眼的功能
像VMLogin这样的虚拟浏览器具有多种功能,如安全的浏览环境、可定制的设置、跨平台的兼容性、更快的浏览速度、广告拦截等等。 虚拟浏览器的不同功能可以为您做什么? 使用虚拟浏览器是浏览互联网和完成其他任务的安全方式,没有风险。您可以在…...
第一个错误的版本
题目 你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。 假设你有 n 个版本 [1, 2, …, n],你想找出…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...

HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...