组件通信有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接受该函数后调用该回调函数将要传递的状态以实参形式传递,便可以向父组件通信。
- 案例 母亲节儿子给母亲红包
```jsx
import { 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 **用于创建上下文对象**
```typescript
import 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>
)
}
}