React---组件通信的方式

1.父子组件通信方式

  • (1)传递数据(父传子)与传递方法(子传父)

基本的Props传递数据与Props传递方法

父传子

1)、定义组件时,声明props形参:
class Person extends React.Component {
  constructor(props) {
     super(props); 
}
render() {
    return (
        <div>       
          姓名:<span>{this.props.name}</span><br/>
      </div>
    );
  }
}

2)、使用组件时,传入参数:
<Person name='张三疯'   >

子传父中,​ 父组件利用props传递方法给子组件,子组件回调这个方法的同时,将数据传递进去,使得父组件的相关方法得到回调,这个时候就可以把数据从子组件传递给父组件了

//1、父组件
class App extends React.Component {
    constructor(){
        super();
        this.state={
            titie:"Home"
        }
    }
    changeData(str){
        console.log("子传给了父亲:",str);
    }
    render = () => (
        <div className="App">
           <Home title={this.state.titie} myFun={this.changeData}/>
           <My title="My"/>
        </div>
    )
};

//2、子组件
class Home extends React.Component {
    constructor(name){
        super();
        this.name=name;
        this.state={
            msg:"hello "
        }
    }
    render = () => (
        <div>
             <h1>我是{this.props.title}</h1>
             <p>{this.state.msg+this.props.title}</p>
             <input 
                type="button" 
                value="传给父亲" 
                onClick={()=>this.props.myFun('HELLO dad')} />
        </div>
    )
}
  • (2)ref标记(父组件拿到子组件的引用,从而调用子组件的方法)

ref的创建用xxx = React.createRef

在父组件中清除子组件的input输入框的value--->this.refs.form.reset()

ps:不过React官方文档建议不要过度依赖ref

2.非父子组件通信方式

  • (1)状态提升(中间人模式)

React中的状态提升概括来说,就是将多个组件需要共享的状态提升到它们最近的父组件上,在父组件上改变这个状态然后通过props分发给子组件。

  • (2)发布订阅模式实现

订阅: token=pubsub.subscribe(‘消息名’,回调函数(‘消息名’,数据))
发布: pubsub.publish(‘消息名’,数据)
清除指定订阅:pubsub.unsubscribe(token|‘消息名’);
清除所有:pubsub.unsubscribeAll()

//下载pubsub依赖
npm i pubsub-js -S

//导入依赖
import pubsub from 'pubsub-js'

child1组件中订阅一个事件

pubsub.subscribe('event1',()=>{alert('child1中订阅的事件')}

child2组件中发布这一事件

alertHandler=()=>{pubsub.publish('event1')}

<button onClick={this.alertHandler}>点击触发child1组件订阅的event事件</button>

注意:child1组件和child2组件都要引入pubsub 才可以使用

  • (3)context状态树传参

context状态树传参,即供应商消费者模式,跨组件通信方案
       1.创建context对象   const GlobalContext = React.createContext()
       2.给提供通信信息的组件加上供应商标签<GlobalContext.Provider/>,直接将return后的最外层<div></div>套在context标签内部即可,在标签上使用value={{属性或方法}}进行传值
       3.给需要通信的组件加上消费者标签<GlobalContext.Consumer/>,需要将<div/>放到回调函数内部,回调函数接受value值,在函数内调用value中的方法,修改value中的属性

import axios from 'axios';
import React, { PureComponent } from 'react'
 
const GlobalContext = React.createContext();//创建context对象
 
export default class App extends PureComponent {
    constructor(){
        super();
        this.state={
            filmdatas:[],
            info:""
        }
        axios({
            url:"test.json"
        }).then(res=>{
            this.setState({
                filmdatas:res.data.data.films
            })
        })
    }
    render() {
        return (
//供应商也就是父组件,用GlobalContext.Provider包裹,并在value里设置供应的数据和方法
            <GlobalContext.Provider value={{
                info:this.state.info,
                changeInfo:(value)=>{
                    this.setState({
                        info:value
                    })}
                }}>
            <div>
                <LeftShow filmdatas={this.state.filmdatas}></LeftShow>
                <RightShow></RightShow>
            </div>
            </GlobalContext.Provider>
        )}
}
class LeftShow extends PureComponent {
    render() {
        return(
//消费者也就是子组件,用GlobalContext.Consumer包裹,并用(value)=>{}的形式给子组件传参
            <GlobalContext.Consumer>{
                (value)=>{
                    return(
                        <div>
                            {this.props.filmdatas.map(item=>
                                <ul key={item.filmId} onClick={()=>{
                                    value.changeInfo(item.synopsis)
                                }}>
                                 <img src={item.poster} alt={item.name}</img>
                                  <li>电影名:{item.name}</li>
                                  <li>上映地:{item.nation}</li>
                                  <li>时长:{item.runtime}分钟</li>
                                </ul>)
                            }           
                        </div>)}}
            </GlobalContext.Consumer>)
}}
class RightShow extends PureComponent {
    render() {
        return (
            <GlobalContext.Consumer>
                {
                    (value)=><div style={{
                                width:"200px",
                                height:"200px",
                                position:"fixed",
                                right:"20px",
                                top:"100px"
                            }}>
                                {value.info}
                            </div>
                }
            </GlobalContext.Consumer>
        )}}
  • (4)redux和mobx

共同点:

  • 两者都是为了解决状态不好管理,无法有效同步的问题而产生的工具。
  • 都是用来统一管理应用状态的工具
  • 某一个状态只有一个可靠的数据来源
  • 操作更新的方式是统一的,并且是可控的
  • 都支持store与react组件,如react-redux,mobx-react

Mobx和Redux的对比总结

1.redux将数据保存在单一的store中,而mobx将数据保存在分散的多个store中
2.redux使用plain object保存数据,需要手动处理变化后的操作,mobx使用observable保存数据,数据变化后自动处理响应的操作。
3.redux使用的是不可变状态,意味着状态只是只读的,不能直接去修改它,而是应该返回一个新的状态,同时使用纯函数;mobx中的状态是可变的,可以直接对其进行修改。
4.mobx相对来说比较简单,在其中有很多的抽象,mobx使用的更多的是面向对象的思维,redux会比较复杂,因为其中的函数式编程思想掌握起来不是那么容易,同时需要借助一系列的中间件来处理异步和副作用。
5.mobx中有更多的抽象和封装,所以调试起来会更加复杂,同时结果也更难以预测,而redux提供可以进行时间回溯的开发工具,同时其纯函数以及更少的抽象,让调试变得更加容易。

mobx:面向对象思维、多个store、observable自动响应变化操作、mobx状态可变,直接修改、更多的抽象和封装,调试复杂,结果难以预测。

redux:函数式编程思想、单一store,plan object保存数据,手动处理变化后的操作、使用不可变状态,意味着状态只读,使用纯函数修改,返回的是一个新的状态、提供时间回溯的开发工具。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值