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/

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容

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