react组件通信

react组件通信是一个常用功能,在做react项目中经常遇到

React组件层级关系

在了解Reat组件通讯之前,先了解下React层级关系。

父子:parent与child1、child2、child1-1、child2-1

兄弟:child1与child2、child1-1与child1-2...

React组件通讯

组件间通信大体有下面几种通讯方式:

1.父—>子:使用props
2.子—>父:使用props回调
3.兄弟组件通信:层层传递props;发布者订阅者模式
4.非嵌套组件间通信:发布者订阅者模式;redux

1.父—>子
父组件向子组件通信,用到比较多。在react中,数据流动是单向的,父组件通过向子组件传递props进行通信,子组件得到props进行相应处理。

patrent.js

import React,{Component} from 'react';
import Child1 from "./child1";//子页面

export class Parent extends Component {
    state = {
        msg:'parent'
    }
    render(){
        return(
            <div>
            <span>父组件通过props向子组件通信:</span>
            <Child1 msg={this.state.msg}/>
            </div>
        )
    }
}
export default Parent;

child1.js

import React,{Component} from 'react';

export class child1 extends Component {
    render(){
        return(
            <span>{this.props.msg}</span> //通过props接收父组件信息
        )
    }
}
export default child1;

如果父组件与子组件之间不止一个层级,如 parent 与child 、 child与child1_1 这样的关系,parent与child1_1通讯可通过 es6中... 扩展运算符进行通信

export class child1 extends Component {
    render(){
        return(
            <div>
                <span>{this.props.msg}</span><br/>
                <Child1_1 {...this.props}/>//多个层级通过扩展运算符...
            </div>         
        )
    }
}
export class child1_1 extends Component {
    render(){
        return(
            <span>parent与child1_1通信:{this.props.msg}</span> 
        )
    }
}

2.子—>父
利用回调函数。
父组件向子组件传递 props ,只是父组件传递的是作用域为父组件自身的函数,子组件调用该函数,将子组件想要传递的信息,作为参数,传递到父组件的作用域中。
parent.js

export class Parent extends Component {
    constructor(props) {
        super(props);
        this.state = {
            msg: 'parent',
            child2Msg:''
        };
      }

    msgCallback(msg) {
        this.setState({
            child2Msg:msg
        });
    }
    render(){
        return(
            <div>
                <div>
                    <span>父组件通过props向子组件通信:</span>
                    <Child1 msg={this.state.msg} />
                </div>
                <div>
                    <span>子组件通过回调函数向父组件通信:{this.state.child2Msg}</span><br/>
                    <Child2 msgCallback={child2 => this.msgCallback(child2)} />
                </div>
            </div>
        )
    }
}

child2.js

import React,{Component} from 'react';

export class child2 extends Component {
    render(){
        return(
            <button onClick={()=>this.props.msgCallback("child2")}>child2</button> 
        )
    }
}
export default child2;

对于层级比较深的子组件与父组件之间通讯,参照父组件与子组件通讯,仍可使用 ... 运算符,将父组件的调用函数传递给子组件

3.兄弟组件通信
A.层层组件传递props
对于没有直接关系的两个组件,就如 child1 与 child2 之间,他们唯一的关联就是拥有相同的父组件parent。参考之前父子通讯方式,可以先通过 child1 向 parent 组件进行通讯,再由parent 向 child2 组件进行通讯,在这里不贴代码了。
不足:当Parent 的 state 发生变化,会触发 Parent 及Parent 的子组件的生命周期,在各个组件中的 componentDidUpdate 方法均被触发。

B.发布者—订阅者模式
这种方式可以避免上面的不足。发布者发布事件,订阅者监听事件并做出反应。
在这里需要一个事件系统,一个简单的事件系统是:

class Event {
    constructor() {
        this.listeners = {};
    }

    on(type, cb, mode) {
        let cbs = this.listeners[type];
        if (!cbs) {
            cbs = [];
        }
        cbs.push(cb);
        this.listeners[type] = cbs;
        return () => {
            this.remove(type, cb);
        };
    }

    emit(type, ...args) {
        const cbs = this.listeners[type];
        if (Array.isArray(cbs)) {
            for (let i = 0; i < cbs.length; i++) {
                const cb = cbs[i];
                if (typeof cb === 'function') {
                    cb(...args);
                }
            }
        }
    }

    remove(type, cb) {
        if (cb) {
            let cbs = this.listeners[type];
            cbs = cbs.filter(eMap => eMap.cb !== cb);
            this.listeners[type] = cbs;
        } else {
            this.listeners[type] = null;
            delete this.listeners[type];
        }
    }
}

export default new Event();

child1页面发布事件

import React,{Component} from 'react';
import Child1_1 from './child1_1';
import Event from '../../utils/event'

export class child1 extends Component {
    componentDidMount() {
        setTimeout(() => {
          // 发布事件
          Event.emit('child1','child1发布消息')
        }, 1000);
      }
    render(){
        return(
            <div>
                <span>{this.props.msg}</span><br/>
                <Child1_1 {...this.props}/>
            </div>         
        )
    }
}
export default child1;

child2页面接收事件

    componentDidMount() {
        //接收事件
        Event.on('child1', (msg) => {
            this.setState({
                msg
            });
        }
        )
    }

我们可以看到,child1 组件的 componentDidMount 中发布了事件,child2 组件对事件做出响应,更新自身 state,在整个通讯过程中,只有 child2 发出了一次生命周期更新渲染。
4.redux
Redux是 JavaScript 状态容器,是第三方的状态管理器,提供可预测化的状态管理,是通讯的中间者。大中型项目可以使用redux,小项目就没什么必要了。redux介绍的东西太多了,在这里我就不具体介绍了,感兴趣的话,大家可以去了解下https://www.redux.org.cn/

以上若有错误或考虑不周之处,敬请指正,谢谢!

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1 组件间通信 父组件向子组件通信React规定了明确的单向数据流,利用props将数据从父组件传递给子组件。故我...
    Dabao123阅读 961评论 0 4
  • react是以组合组件的形式组织的,那么组件间是如何传递信息的呢? 父组件向子组件通信 parent组件传给chi...
    DCbryant阅读 482评论 0 0
  • 在现代的三大框架中,其中两个Vue和React框架,组件间传值方式有哪些? 组件间的传值方式 组件的传值场景无外乎...
    mdiep阅读 1,303评论 0 0
  • 父子 父子通信(回调函数)[组件通信] 父传子:父组件传一个函数给子组件,子组件在恰当的时候调用 子传父:1.父组...
    追夢的蚂蚁阅读 156评论 0 0
  • 2018-09-3 周一 今天是什么日子 起床:5:00 就寝:11:00 天气:晴朗 心情:愉快 纪念日:升旗的...
    渺尘03阅读 707评论 0 0