React非父子之间的通信方法:
1.状态提升 -- 中间人模式(通过父组件来通信,一级一级的分发)
2.发布订阅者模式 -- 不需要借助任何人的力量,纯原生js的方式(设计模式中的一种)
3.context状态树传参(消费者、生产者模式) -- 独立实现非父子之间通信的解决方案(类似于vue中的bus)
订阅者交出一个回调函数,传给中央服务,发布者已发布,就调用中央服务的回调函数
点击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