组件通信有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 = {

    1. money: 2000

    } } render() {

    return (

    1. <div>
    2. // 通过自定义属性的形式绑定在子组件身上
    3. <Son Shf={this.state.money} />
    4. </div>

    ) } }

class Son extends Component

{ render() { return ( <> // 直接使用传递过来的属性

我爸给了我:{this.props.Shf}

</> ) } }

  1. <a name="ieYEh"></a>
  2. ### 子父组件通信
  3. 利用回调函数,可以实现子组件向父组件通信:父组件将一个函数作为props传递给子组件,子组件通过this.props接受该函数后调用该回调函数将要传递的状态以实参形式传递,便可以向父组件通信。
  4. - 案例 母亲节儿子给母亲红包
  5. ```jsx
  6. import { Component } from 'react'
  7. interface S {
  8. xJK: number
  9. }
  10. interface P {
  11. }
  12. export default class App extends Component<P, S> {
  13. constructor(props: P) {
  14. super(props)
  15. this.state = {
  16. xJK: 2000
  17. }
  18. }
  19. count = 0 // 控制子组件执行次数
  20. momDay = (val: number): void => {
  21. if (!this.count) {
  22. this.setState({
  23. xJK: this.state.xJK + val
  24. })
  25. }
  26. this.count += 1
  27. }
  28. render() {
  29. return (
  30. <div>
  31. <h1>APP组件</h1>
  32. <Son momDay={this.momDay} />
  33. <p>{this.state.xJK}</p>
  34. </div>
  35. )
  36. }
  37. }
  38. // Son组件定义如下
  39. interface PP {
  40. momDay: (val: number) => void
  41. }
  42. interface SS{
  43. hongBao:number
  44. }
  45. class Son extends Component<PP,SS>{
  46. constructor(props: PP) {
  47. super(props)
  48. this.state = {
  49. hongBao: 888
  50. }
  51. }
  52. render() {
  53. return (
  54. <>
  55. <h1>Son组件</h1>
  56. <button onClick={()=>this.props.momDay(this.state.hongBao)}>母亲节给妈咪红包</button>
  57. </>
  58. )
  59. }
  60. }

非嵌套组件通信(非父子组件通信)

使用自定义事件的方式 或者 二者共同父组件的context对象进行通信,但是如果采用后者,会增加子组件和父组件之间的耦合度,如果组件层次较深找到二者共同的父组件不是一件容易的事,所以尽量避免该方式

  • 案例: 姐姐打弟弟 ```jsx import { Component } from ‘react’ export default class App extends Component { brother: any = {} kick = () => { this.brother.setCryFlag() }

    render() { return (

    1. <>
    2. App
    3. <Sister kick={this.kick} />
    4. {/* ref它的值是一个箭头函数,
    5. 参数el就是Brother组件,
    6. this.brother = el 将Brother赋值给了this.brother,
    7. brother是自定义的属性名字
    8. */}
    9. <Brother ref={el => this.brother = el} />
    10. </>

    ) } }

// Sister 组件定义 interface PP { kick: () => void } class Sister extends Component {

render() { return ( <>

Sister

</> ) } }

// Brother 组件定义 interface PPP {

} interface SSS { cryFlag: boolean } class Brother extends Component { constructor(props: PPP) { super(props) this.state = { cryFlag: false, } } // 组件自己的state最好自己控制, setCryFlag = () => { this.setState({ cryFlag: !this.state.cryFlag }) } render() { return ( <>

Brother

{ this.state.cryFlag && 组件通信 - 图1 } </> ) } }

  1. <a name="C4nzl"></a>
  2. ### 跨组件通信
  3. 在React中没有类似vue中的事件总线来解决这个问题,我们只能借助它们共同的父级组件来实现,将非父子关系转换成多维度的父子关系。React提供来 `context` api来实现跨组件通信(类似vue中的提供provide / 注入inject),React16.3之后的context api较之前的好用<br />src目录下创建context/index.ts **用于创建上下文对象**
  4. ```typescript
  5. import React, { createContext } from 'react'
  6. const context: React.Context<number> = createContext(0)
  7. export default context
  1. import { Component } from 'react'
  2. import context from './context' // 引入
  3. interface P{
  4. }
  5. interface S{
  6. money:number
  7. }
  8. export default class App extends Component<P,S> {
  9. constructor(props:P){
  10. super(props)
  11. this.state={
  12. money:20000
  13. }
  14. }
  15. render() {
  16. return (
  17. <div>
  18. <context.Provider value={this.state.money}> // value属性绑定需要传递的数据
  19. <Father/>
  20. </context.Provider>
  21. </div>
  22. )
  23. }
  24. }
  25. // Father 组件定义
  26. class Father extends Component {
  27. render() {
  28. return (
  29. <div>
  30. <Son/>
  31. </div>
  32. )
  33. }
  34. }
  35. // Son 组件定义
  36. class Son extends Component {
  37. render() {
  38. return (
  39. <div>
  40. <Grandson/>
  41. </div>
  42. )
  43. }
  44. }
  45. // Grandson 组件定义
  46. class Grandson extends Component {
  47. // 子孙组件通过contextType来接受context这个上下文对象
  48. static contextType=context;
  49. render() {
  50. return (
  51. <div>
  52. {/* 子组件通过this.context直接调用数据即可 */}
  53. grandson:{this.context}
  54. </div>
  55. )
  56. }
  57. }