react组件通信

作者: ZhangYu31 | 来源:发表于2019-05-10 17:32 被阅读71次

    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/

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

    相关文章

      网友评论

        本文标题:react组件通信

        本文链接:https://www.haomeiwen.com/subject/nqadoqtx.html