组件通信有5种:父子组件通信,子父组件通信、非嵌套组件通信(非父子组件通信)、跨组件通信、多组件状态管理(redux、mobx)。
父子组件通信
React数据流动是单向的,父组件向子组件通信是最常见的。父组件通过props向子组件传递需要的信息
实现核心思想:父组件将想要传递的状态通过自定义属性的形式绑定在子组件身上
案例 爸爸给儿子生活费 ```jsx import { Component } from ‘react’ interface S { money: number } interface P { Shf?: number } export default class App extends Component
{ constructor(props: P) { super(props) this.state = {
money: 2000
} } render() {
return (
<div>// 通过自定义属性的形式绑定在子组件身上<Son Shf={this.state.money} /></div>
) } }
class Son extends Component
{ render() { return ( <> // 直接使用传递过来的属性
我爸给了我:{this.props.Shf}
</> ) } }
<a name="ieYEh"></a>### 子父组件通信利用回调函数,可以实现子组件向父组件通信:父组件将一个函数作为props传递给子组件,子组件通过this.props接受该函数后调用该回调函数将要传递的状态以实参形式传递,便可以向父组件通信。- 案例 母亲节儿子给母亲红包```jsximport { Component } from 'react'interface S {xJK: number}interface P {}export default class App extends Component<P, S> {constructor(props: P) {super(props)this.state = {xJK: 2000}}count = 0 // 控制子组件执行次数momDay = (val: number): void => {if (!this.count) {this.setState({xJK: this.state.xJK + val})}this.count += 1}render() {return (<div><h1>APP组件</h1><Son momDay={this.momDay} /><p>{this.state.xJK}</p></div>)}}// Son组件定义如下interface PP {momDay: (val: number) => void}interface SS{hongBao:number}class Son extends Component<PP,SS>{constructor(props: PP) {super(props)this.state = {hongBao: 888}}render() {return (<><h1>Son组件</h1><button onClick={()=>this.props.momDay(this.state.hongBao)}>母亲节给妈咪红包</button></>)}}
非嵌套组件通信(非父子组件通信)
使用自定义事件的方式 或者 二者共同父组件的context对象进行通信,但是如果采用后者,会增加子组件和父组件之间的耦合度,如果组件层次较深找到二者共同的父组件不是一件容易的事,所以尽量避免该方式
案例: 姐姐打弟弟 ```jsx import { Component } from ‘react’ export default class App extends Component { brother: any = {} kick = () => { this.brother.setCryFlag() }
render() { return (
<>App<Sister kick={this.kick} />{/* ref它的值是一个箭头函数,参数el就是Brother组件,this.brother = el 将Brother赋值给了this.brother,brother是自定义的属性名字*/}<Brother ref={el => this.brother = el} /></>
) } }
// Sister 组件定义
interface PP {
kick: () => void
}
class Sister extends Component
render() { return ( <>
Sister
</> ) } }// Brother 组件定义 interface PPP {
}
interface SSS {
cryFlag: boolean
}
class Brother extends Component
Brother
{ this.state.cryFlag &&
}
</>
)
}
}
<a name="C4nzl"></a>### 跨组件通信在React中没有类似vue中的事件总线来解决这个问题,我们只能借助它们共同的父级组件来实现,将非父子关系转换成多维度的父子关系。React提供来 `context` api来实现跨组件通信(类似vue中的提供provide / 注入inject),React16.3之后的context api较之前的好用<br />src目录下创建context/index.ts **用于创建上下文对象**```typescriptimport React, { createContext } from 'react'const context: React.Context<number> = createContext(0)export default context
import { Component } from 'react'import context from './context' // 引入interface P{}interface S{money:number}export default class App extends Component<P,S> {constructor(props:P){super(props)this.state={money:20000}}render() {return (<div><context.Provider value={this.state.money}> // value属性绑定需要传递的数据<Father/></context.Provider></div>)}}// Father 组件定义class Father extends Component {render() {return (<div><Son/></div>)}}// Son 组件定义class Son extends Component {render() {return (<div><Grandson/></div>)}}// Grandson 组件定义class Grandson extends Component {// 子孙组件通过contextType来接受context这个上下文对象static contextType=context;render() {return (<div>{/* 子组件通过this.context直接调用数据即可 */}grandson:{this.context}</div>)}}
