一.组件通信的意义
组件是独立且封闭的单元,默认情况下组件只能使用自己的数据(state)
组件化开发的过程中,完整的功能会拆分多个组件,在这个过程中不可避免的需要互相传递一些数据
为了能让各组件之间可以进行互相沟通,数据传递,这个过程就是组件通信
- 父子关系 - 最重要的
- 兄弟关系 - 自定义事件模式产生技术方法 eventBus / 通过共同的父组件通信
- 其它关系 - mobx / redux / 基于hook的方案
二.父传子的实现
父组件提供要传递的数据 -
state
给子组件标签
添加属性
值为 state中的数据子组件中通过
props
接收父组件中传过来的数据
- 类组件使用this.props获取props对象
- 函数式组件直接通过参数获取props对象
import React from 'react'
// 函数式组件
const SonF=(props)=>{
return <div>这是函数式组件{props.msg}</div>
}
// 类组件
class SonC extends React.Component{
render(){
return <div>这是类组件{this.props.msg}</div>
}
}
class App extends React.Component{
state={
message:'这是父组件中的数据'
}
render(){
return (
<div>
{/*子组件中绑定属性,属性名可以自定义 保持语义化 */}
<SonC msg={this.state.message}></SonC>
<SonF msg={this.state.message}></SonF>
</div>
)
}
}
export default App;
props说明
1. props是只读对象(readonly)
根据单项数据流的要求,子组件只能读取props中的数据,不能进行修改
2. props可以传递任意数据
数字、字符串、布尔值、数组、对象、函数、JSX
解构赋值用法
用哪个在参数位置解构那个,比上面props.xxxxx用法简单很多
const SonF=({list,getmsg,child})=>{
return (
<div>
<div>这是函数式组件{list.map((item)=><p>{item}</p>)}</div>
<button onClick={getmsg}>传递函数</button>
{child}
</div>
)
}
三.子传父
- 父组件提供一个回调函数 - 用于接收数据
- 将函数作为属性的值,传给子组件
- 子组件通过props调用 回调函数
- 将子组件中的数据作为参数传递给回调函数
import React from 'react'
// 子组件
function Son(props) {
function handleClick() {
// 调用父组件传递过来的回调函数 并注入参数
props.changeMsg('this is newMessage')
}
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
五.兄弟通信
将B组件中的数据传给A
技术方案:先把B中的数据通过子传父传递给App
再把App中的数据通过父传子传递给A
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
六.跨组件通信Context
如图实现APP和C组件之间通信
实现步骤
1.创建Context对象 导出 Provider 和 Consumer对象
const { Provider, Consumer } = createContext()
2.使用Provider包裹根组件提供数据
<Provider value={this.state.message}>
{/* 根组件 */}
</Provider>
3、需要用到数据的组件使用Consumer包裹获取数据
<Consumer >
{value => /* 基于 context 值进行渲染*/}
</Consumer>
import React ,{createContext} from "react";
// 1..创建Context对象 导出 Provider 和 Consumer对象
const {Provider,Consumer}=createContext()
// 2.消费数据
function SonB(){
return(
<Consumer>
{value=>
<div> {value}</div>
}
</Consumer>
)
}
const SonA=()=>{
return(
<SonB></SonB>
)
}
// 2.提供数据
class App extends React.Component{
state={
message:'this is message'
}
render() {
return(
<Provider value={this.state.message}>
<div>
<SonA></SonA>
</div>
</Provider>
)
}
}
export default App