React类式组件非父子组件之间的通信

导读:本篇文章讲解 React类式组件非父子组件之间的通信,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

React非父子之间的通信方法:
1.状态提升 -- 中间人模式(通过父组件来通信,一级一级的分发)
2.发布订阅者模式 -- 不需要借助任何人的力量,纯原生js的方式(设计模式中的一种)
3.context状态树传参(消费者、生产者模式) -- 独立实现非父子之间通信的解决方案(类似于vue中的bus)

1、订阅发布者模式
在这里插入图片描述

订阅者交出一个回调函数,传给中央服务,发布者已发布,就调用中央服务的回调函数
点击Child2中的按钮,执行Child1中的回调函数

import React, { Component } from 'react'

const observer = { // 1.新建一个订阅者、发布者的对象
    list:[],
    // 6.接收传过来的回调callback
    subscribe(callback){ // 订阅者(注册),不是固定的
        // 7.把回调函数存到数组中
        this.list.push(callback)
    },
    // 8.然后发布者就会遍历list,让里面所有的回调函数执行
    dispatch(data){ // 发布者,不是固定的
      this.list.forEach(item=>{
          // 12.执行回调函数,data 是发布者发布的东西
          item(data)
      })
    }
}

// 2.定义Child1兄弟组件(订阅者)
class Child1 extends Component{
    // 4.Child1创建成功, DOM挂载完成的时候,把回调函数传给订阅者
    // 等价于vue中的mounted
    componentDidMount(){ // 也是一个生命周期(自动被执行)
        // 5.Child1一创建,就调用订阅方法subscribe,把child1定义的回调函数(data)={}传过去
        observer.subscribe((data)=>{
            console.log("child1定义的回调函数",data)
        })
    }

    render(){
        return <div style={{background:"red"}}>我是微信用户(订阅者)</div>
    }
}

// 3.定义Child2兄弟组件(发布者)
class Child2 extends Component{
    render(){
        return <div style={{background:"yellow"}}>
            我是微信公众号发布者
            {/* 9.发布,调用handleClick方法 */}
            <button onClick={this.handleClick}>发布</button>
        </div>
    }
    // 10.发布
    handleClick= ()=>{
        // 11.调用observer对象中的dispatch方法,发布一些东西
        observer.dispatch("来自child2的问候")
    }
}

export default class App extends Component {
    render() {
        return (
            <div>
                <Child1/>
                <Child2/>
            </div>
        )
    }
}

2.context状态树传参 -- 原生js中的消费者、生产者模式

import React, { Component } from 'react'
// 1.创建一个context对象
const GlobalContext = React.createContext() 

class Child1 extends Component{
    render(){
        {/* 5.充钱(GlobalContext.Consumer消费者) */}
        return <GlobalContext.Consumer>
            {
                // 6.使用服务(通信)(固定写法)
                context=>(
                    // 13.Child1中调用供应商state中的text这个状态
                    <div>child1--{context.text}</div>
                )
            }
        </GlobalContext.Consumer>
    }
}


class Child2 extends Component{
    render(){
        {/* 7.也充钱了,可以通信 */}
        return <GlobalContext.Consumer>
            {
                context=> (
                    <div>child2-{context.call}
                        {/* 9.问候Child1(通信) */}
                        <button onClick={()=>this.handleClick(context)}>
                            child2通信
                        </button>
                    </div>
                )
            }
            </GlobalContext.Consumer>     
    }

    // 10.
    handleClick=(context)=>{
        {/* 
          15.调用changeState方法来修改状态,问候Child1,
             只要状态修改了,Child1组件中就会收到新的状态 
       */}
        context.changeState("来自child2的问候")
    }
}

class Child3 extends Component{
    render(){
        {/* 8.Child3没有包裹GlobalContext.Consumer,所以Child3无法通信 */}
        return <div>child3</div>
    }
}

export default class App extends Component {
  // 11.定义公共的状态
    state ={
        text:"私人服务"
    }

	// 14.修改状态,data 是来自Child2传来的参数
    changeState= (data)=>{
        this.setState({
            text:data
        })
    }

    render() {
        return (
            /*
              2.在项目的根组件最外层包裹一层基站(GlobalContext.Provider供应商、生产者),
                这样将来子组件才能通信
            */        
            <GlobalContext.Provider 
              // 4.Child1、Child2充钱了,就可以给他们提供服务,Child3没充钱拿不到东西
              value={{
                  sms:"短信服务",
                  call:"电话服务",
                  // 12.调用state,把text这个状态传进来
                  text:this.state.text,
                  changeState:this.changeState
              }}
            >
                <div>
                {/* 3.子组件,Child1、Child2充钱了,Child3没充钱 */}
                    <Child1/>
                    <Child2/>
                    <Child3/>
                </div>
            </GlobalContext.Provider>
        )
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/4574.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!