组件通信
1、父传子
实现步骤:
- 父组件提供要传递的数据 -
state
- 给子组件标签
添加属性
值为 state中的数据 - 子组件中通过
props
接收父组件中传过来的数据
-
- 类组件使用this.props获取props对象
- 函数式组件直接通过参数获取props对象
import React from 'react'
// 函数式子组件
function FSon(props) {
console.log(props)
return (
<div>
子组件1
{props.msg}
</div>
)
}
// 类子组件
class CSon extends React.Component {
render() {
return (
<div>
子组件2
{this.props.msg}
</div>
)
}
}
// 父组件
class App extends React.Component {
state = {
message: 'this is message'
}
render() {
return (
<div>
<div>父组件</div>
<!-- 函数组件和类组件的传值方式相同-->
<FSon msg={this.state.message} />
<CSon msg={this.state.message} />
</div>
)
}
}
export default App
props说明:
1. props是只读对象(readonly)
根据单项数据流的要求,子组件只能读取props中的数据,不能进行修改
2. props可以传递任意数据
数字、字符串、布尔值、数组、对象、函数、JSX
3.props依然可以解构赋值
-
在方法内进行具体的解构赋值
const { list, userInfo,getMsg } = props
-
在函数传递处解构赋值
function Son({list,userInfo}){ // 在函数中直接使用 list等 }
// 完整父传子
class App extends React.Component {
state = {
message: 'this is message'
}
render() {
return (
<div>
<div>父组件</div>
<FSon
msg={this.state.message}
age={20}
isMan={true}
cb={() => { console.log(1) }}
child={<span>this is child</span>}
/>
<CSon msg={this.state.message} />
</div>
)
}
}
2、子传父
父组件给子组件传递回调函数,子组件调用:
- 父组件提供一个回调函数 - 用于接收数据
- 将函数作为属性的值,传给子组件
- 子组件通过props调用 回调函数
- 将子组件中的数据作为参数传递给回调函数
import React from 'react'
// 子组件
function Son(props) {
function handleClick() {
// 调用父组件传递过来的回调函数 并注入参数
props.changeMsg('this is newMessage')
// 或者
const sonMsg = 'son data'
props.changeMsg(sonMsg)
}
return (
<div>
{props.msg}
<button onClick={handleClick}>change</button>
</div>
)
}
class App extends React.Component {
state = {
message: 'this is message'
}
// 提供回调函数
changeMessage = (newMsg) => {
console.log('子组件传过来的数据:',newMsg)
this.setState({
message: newMsg
})
}
render() {
return (
<div>
<div>父组件</div>
<Son
msg={this.state.message}
// 传递给子组件
changeMsg={this.changeMessage}
/>
</div>
)
}
}
export default App
3、兄弟组件通信
核心思路: 通过状态提升机制,利用共同的父组件实现兄弟通信
实现步骤
- 将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态
-
- 提供共享状态
- 提供操作共享状态的方法
- 要接收数据状态的子组件通过 props 接收数据
- 要传递数据状态的子组件通过props接收方法,调用方法传递数据
import React from 'react'
// 子组件A
function SonA(props) {
return (
<div>
SonA
{props.msg}
</div>
)
}
// 子组件B
function SonB(props) {
return (
<div>
SonB
<button onClick={() => props.changeMsg('new message')}>changeMsg</button>
</div>
)
}
// 父组件
class App extends React.Component {
// 父组件提供状态数据
state = {
message: 'this is message'
}
// 父组件提供修改数据的方法
changeMsg = (newMsg) => {
this.setState({
message: newMsg
})
}
render() {
return (
<>
{/* 接收数据的组件 */}
<SonA msg={this.state.message} />
{/* 修改数据的组件 */}
<SonB changeMsg={this.changeMsg} />
</>
)
}
}
export default App
4、跨组件通信
在vue中,我们了解过跨组件通信的机制,provide和inject。在react中,我们同样拥有一套解决跨层级通信的方法,这便是context,context提供了一个无需为每层组件手动添加props就能在组件之间进行数据传递的方法。
实现步骤:
-
创建Context对象,使用其中的Provider和Consumer对象
import createContext from 'react' const { Provider, Consumer } = createContext()
-
使用Provider包裹上层组件提供的数据
<Provider value={this.state.message}> {/* 根组件 */} </Provider>
-
需要用到传递数据的组件使用Consumer包裹获取数据
<Consumer > {value => /* 基于 context 值进行渲染*/} {value => <span>{value}</span>} </Consumer>
-
注意事项
- 上层组件和下层组件的关系是相对的,只要存在这种关系就可以使用。
- 通常我们使用App作为数据提供方
- 代码中涉及到的语法基本都是固定的如使用value提供数据,使用{value => …}接受数据渲染等
import React, { createContext } from 'react'
// 1. 创建Context对象
const { Provider, Consumer } = createContext()
// 3. 消费数据
function ComC() {
return (
<Consumer >
{value => <div>{value}</div>}
</Consumer>
)
}
function ComA() {
return (
<ComC/>
)
}
// 2. 提供数据
class App extends React.Component {
state = {
message: 'this is message'
}
render() {
return (
<Provider value={this.state.message}>
<div className="app">
<ComA />
</div>
</Provider>
)
}
}
export default App