react之組件通信

需要組件之進行通信的幾種情況:

  • 父組件向子組件通信
  • 子組件向父組件通信
  • 跨級組件通信
  • 沒有嵌套關系組件之間的通信

1. 父組件向子組件通信

React數(shù)據流動是單向的,父組件向子組件通信也是最常見的;父組件通過props向子組件傳遞需要的信息妖滔。

父組件:

<StrategyTable
  maxLength={2}
  styleName="strategy-able"
  onRowClick={this.onRowClick}
  delayTime={500}
  isRefresh={false}
 />

子組件:

import PropTypes from 'prop-types';

  static propTypes = {
    maxLength: PropTypes.number,
    isSignalStk: PropTypes.bool, 
    onRowClick: PropTypes.func,
    getLastData: PropTypes.func,
    onRef: PropTypes.func,
    assetId: PropTypes.string,
    sessionId: PropTypes.string,
    isDataSeparate: PropTypes.bool,
    delayTime: PropTypes.number,
    isRefresh: PropTypes.bool,
  }
  static defaultProps = {
    maxLength: -1,
    isSignalStk: false,
    onRowClick: () => {},
    getLastData: () => {},
    onRef: () => {},
    assetId: '',
    sessionId: '',
    isDataSeparate: false,
    delayTime: 0,
    isRefresh: true,
  }

  constructor(props) {
    super(props);
    this.state = {
      maxLength: this.props.maxLength, // 子組件通過 this.props.屬性名 來獲取父組件傳來的參數(shù)
    };
  }

2. 子組件向父組件通信

利用回調函數(shù)參數(shù)獲取子組件傳來的值邢锯。

父組件:

import React, { Component } from 'react';

export default class ListWrap extends Component {

getSunData = (val) => {
  this.text = val;
}

  render() {
     return (
       <div>
        <sunComponent onRowClick={this.getSunData}/>
      </div>
    );
  }
}

子組件:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

export default class sunComponent extends Component {

  static propTypes = {
    onRowClick: PropTypes.func,
  }
  static defaultProps = {
    onRowClick: () => {},
  }

  render() {
     return (
       <div>
        <ul>
          <li onClick={() => {this.props.onRowClick('子組件信息')}}>我是子組件信息</li>
        </ul>
      </div>
    );
  }
}

3. 跨級組件通信

跨級組件通信有兩種方法:
1. 層層傳遞props

例如A組件和B組件之間要進行通信,先找到A和B公共的父組件,A先向C組件通信,C組件通過props和B組件通信,此時C組件起的就是中間件的作用

2.使用context

context是一個全局變量,像是一個大容器,在任何地方都可以訪問到,我們可以把要通信的信息放在context上,然后在其他組件中可以隨意取到;
但是React官方不建議使用大量context,盡管他可以減少逐層傳遞,但是當組件結構復雜的時候,我們并不知道context是從哪里傳過來的;而且context是一個全局變量,全局變量正是導致應用走向混亂的罪魁禍首.

props傳參就不多說了鸠删,接下來重點說一下context。

對于父組件,也就是Context生產者遥昧,需要通過一個靜態(tài)屬性childContextTypes聲明提供給子組件的Context對象的屬性,并實現(xiàn)一個實例getChildContext方法,返回一個代表Context的純對象 (plain object) 鸥诽。

import React from 'react'
import PropTypes from 'prop-types'

class MiddleComponent extends React.Component {
  render () {
    return <ChildComponent />
  }
}

class ParentComponent extends React.Component {
  // 聲明Context對象屬性
  static childContextTypes = {
    propA: PropTypes.string,
    methodA: PropTypes.func
  }
  
  // 返回Context對象,方法名是約定好的
  getChildContext () {
    return {
      propA: 'propA',
      methodA: () => 'methodA'
    }
  }
  
  render () {
    return <MiddleComponent />
  }
}

而對于Context的消費者箕憾,通過如下方式訪問父組件提供的Context牡借。

import React from 'react'
import PropTypes from 'prop-types'

class ChildComponent extends React.Component {
  // 聲明需要使用的Context屬性
  static contextTypes = {
    propA: PropTypes.string,
  }
  
  render () {
    const {
      propA,
      methodA
    } = this.context
    
    console.log(`context.propA = ${propA}`)  // context.propA = propA
    console.log(`context.methodA = ${methodA}`)  // context.methodA = undefined
    
    return ...
  }
}

子組件需要通過一個靜態(tài)屬性contextTypes聲明后,才能訪問父組件Context對象的屬性袭异,否則钠龙,即使屬性名沒寫錯,拿到的對象也是undefined御铃。

幾個可以直接獲取Context的地方:
實際上碴里,除了實例的context屬性(this.context),React組件還有很多個地方可以直接訪問父組件提供的Context上真。比如構造方法:
constructor(props, context)

比如生命周期:
componentWillReceiveProps(nextProps, nextContext)
shouldComponentUpdate(nextProps, nextState, nextContext)
componetWillUpdate(nextProps, nextState, nextContext)

4. 沒有嵌套關系的組件通信

在componentDidMount事件中,如果組件掛載完成,再訂閱事件;在組件卸載的時候,在componentWillUnmount事件中取消事件的訂閱;
以常用的發(fā)布/訂閱模式舉例,借用Node.js Events模塊的瀏覽器版實現(xiàn)咬腋。

下面例子中的組件關系: List1和List2沒有任何嵌套關系,App是他們的父組件;

實現(xiàn)這樣一個功能: 點擊List2中的一個按鈕,改變List1中的信息顯示
首先需要項目中安裝events 包:
npm install events --save

在src下新建一個util目錄里面建一個events.js

import { EventEmitter } from 'events';

export default new EventEmitter();

list1.jsx

import React, { Component } from 'react';
import emitter from '../util/events';

class List extends Component {
    constructor(props) {
        super(props);
        this.state = {
            message: 'List1',
        };
    }
    componentDidMount() {
        // 組件裝載完成以后聲明一個自定義事件
        this.eventEmitter = emitter.addListener('changeMessage', (message) => {
            this.setState({
                message,
            });
        });
    }
    componentWillUnmount() {
        emitter.removeListener(this.eventEmitter);
    }
    render() {
        return (
            <div>
                {this.state.message}
            </div>
        );
    }
}

export default List;

List2.jsx

import React, { Component } from 'react';
import emitter from '../util/events';

class List2 extends Component {
    handleClick = (message) => {
        emitter.emit('changeMessage', message);
    };
    render() {
        return (
            <div>
                <button onClick={this.handleClick.bind(this, 'List2')}>
                  點擊我改變List1組件中顯示信息
                </button>
            </div>
        );
    }
}

APP.jsx

import React, { Component } from 'react';
import List1 from './components/List1';
import List2 from './components/List2';


export default class App extends Component {
    render() {
        return (
            <div>
                <List1 />
                <List2 />
            </div>
        );
    }
}

總結:

  • 父組件向子組件通信: props
  • 子組件向父組件通信: 回調函數(shù)
  • 跨級組件通信: 層層組件傳遞props/context
  • 沒有嵌套關系組件之間的通信: EventEmitter
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市睡互,隨后出現(xiàn)的幾起案子根竿,更是在濱河造成了極大的恐慌,老刑警劉巖就珠,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寇壳,死亡現(xiàn)場離奇詭異,居然都是意外死亡嗓违,警方通過查閱死者的電腦和手機九巡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蹂季,“玉大人冕广,你說我怎么就攤上這事疏日。” “怎么了撒汉?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵沟优,是天一觀的道長。 經常有香客問我睬辐,道長挠阁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任溯饵,我火速辦了婚禮侵俗,結果婚禮上,老公的妹妹穿的比我還像新娘丰刊。我一直安慰自己隘谣,他們只是感情好,可當我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布啄巧。 她就那樣靜靜地躺著寻歧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪秩仆。 梳的紋絲不亂的頭發(fā)上码泛,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天,我揣著相機與錄音澄耍,去河邊找鬼噪珊。 笑死,一個胖子當著我的面吹牛逾苫,可吹牛的內容都是我干的卿城。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼铅搓,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了搀捷?” 一聲冷哼從身側響起星掰,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嫩舟,沒想到半個月后氢烘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡家厌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年播玖,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片饭于。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡蜀踏,死狀恐怖维蒙,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情果覆,我是刑警寧澤颅痊,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站局待,受9級特大地震影響斑响,放射性物質發(fā)生泄漏。R本人自食惡果不足惜钳榨,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一舰罚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧薛耻,春花似錦沸停、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至候醒,卻和暖如春能颁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背倒淫。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工伙菊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人敌土。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓镜硕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親返干。 傳聞我的和親對象是個殘疾皇子兴枯,可洞房花燭夜當晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內容