React入門(四)

組件通信


復(fù)合組件:父組件嵌套子組件

方案一:屬性傳遞(適用于父與子)

???????調(diào)取子組件的時(shí)候,把信息基于屬性的方式傳遞給子組件(子組件props中存儲(chǔ)傳遞的信息),這種方式只能是父組件把信息傳遞子組件,子組件無法直接地把信息傳遞給父組件,也就是說屬性傳遞信息是單向傳遞的。不過利用回調(diào)函數(shù)機(jī)制也可以實(shí)現(xiàn)子改父的效果,即父組件把一個(gè)函數(shù)通過屬性或者上下文的方式傳遞給子組件,子組件中只要把這個(gè)方法執(zhí)行即可

/*HEAD*/
class Head extends React.Component {
    render() {
        return <div className='panel-heading'>
            <h3 className='panel-title'>
                {/*子組件通過屬性獲取父組件傳遞的狀態(tài)*/}
                點(diǎn)擊次數(shù):{this.props.count}
            </h3>
        </div>;
    }
}

/*BODY*/
class Body extends React.Component {
    render() {
        return <div className='panel-body'>
            <button className='btn btn-success'
                    {/*子組件通過屬性獲取父組件傳遞的方法*/}
                    onClick={this.props.callBack}>點(diǎn)我啊!
            </button>
        </div>;
    }
}

/*PANEL*/
class Panel extends React.Component {
    constructor() {
        super();
        this.state = {n: 0};
    }

    fn = () => {
        // 修改PANEL的狀態(tài)信息
        this.setState({
            n: this.state.n + 1
        });
    };

    render() {
        return <section className='panel panel-default' style={{width: '50%', margin: '20px auto'}}>
            {/*父組件中在調(diào)取子組件的時(shí)候,把信息通過屬性傳遞給子組件*/}
            <Head count={this.state.n}/>

            {/*父組件把自己的一個(gè)方法基于屬性傳遞給子組件,目的是在子組件中執(zhí)行這個(gè)方法*/}
            <Body callBack={this.fn}/>
        </section>;
    }
}
效果演示

方案二:發(fā)布訂閱方式

1.調(diào)用父組件創(chuàng)建一個(gè)屬于自己的事件池
2.在子組件中把修改本身狀態(tài)的方法放到事件池中
3.在點(diǎn)擊按鈕的時(shí)候,通知事件池中的方法執(zhí)行即可

方案三:基于上下文進(jìn)行傳遞

???????父組件先把需要給后代元素(包括孫子元素)使用的信息都設(shè)置好(設(shè)置在上下文中),后代組件需要用到父組件中的信息,主動(dòng)去父組件中調(diào)取使用即可

  • 方法一
    1.父組件設(shè)置childContextTypesgetChildContext
    2.子組件通過contextTypes獲取上下文
    // 父組件設(shè)置信息
    static childContextTypes = {
        // 設(shè)置上下文中信息值的類型,需借助prop-types
        n: PropTypes.number,
        m: PropTypes.number
    };
    getChildContext() {
        // RETURN的是啥,相當(dāng)相當(dāng)于往上下文中放了啥
        let {count: {n = 0, m = 0}} = this.props;
        return {
            n,
            m
        };
    }
    
    // 子組件主動(dòng)獲取需要的信息
    static contextTypes = {
        // 首先類型需要和設(shè)置時(shí)類型一致,否則報(bào)錯(cuò);然后根據(jù)需求提取上下文的內(nèi)容即可
        n: PropTypes.number,
        m: PropTypes.number
    };
    
  • 方法二
    1.React.createContext()創(chuàng)建上下文
    2.通過ThemeContext.ProviderThemeContext.Consumer標(biāo)簽進(jìn)行信息傳遞

屬性傳遞 VS 上下文傳遞

1.接收值的方式:屬性傳遞時(shí)子組件通過props被動(dòng)接收傳遞的值,而上下文傳遞時(shí)子組件是主動(dòng)通過contextTypes挑選自己需要的值
2.值的可修改性:屬性傳遞中父?jìng)髯拥膶傩詫儆?strong>只讀屬性,不可修改,最多只能通過defaultProps設(shè)置未傳時(shí)的默認(rèn)值,而上下文傳遞時(shí)子組件是可以修改獲取到的上下文信息的(但是不會(huì)影響到父組件中的信息,其它組件不受影響)
3.后代接收方式:屬性傳遞只能一層層地進(jìn)行傳遞,即若想實(shí)現(xiàn)父?jìng)鲗O,則必須先父?jìng)髯?,再進(jìn)行子傳孫才可實(shí)現(xiàn),而上下文傳遞時(shí)后代組件可以直接使用父組件設(shè)置好的上下文信息,不需要一層層進(jìn)行傳遞
4.操作難易程度:屬性傳遞操作起來相對(duì)方便簡(jiǎn)單,而上下文傳遞操作起來相對(duì)繁瑣一些


平行組件:兄弟組件或者毫無關(guān)系的兩個(gè)組件

方案一:讓兩個(gè)平行組件擁一個(gè)共同的父組件

???????父組件中有一些信息,父組件把一個(gè)方法傳遞給A,A中把方法執(zhí)行(方法執(zhí)行修改父組件信息值),父組件再把最新的信息傳遞給B即可,等價(jià)于A操作,影響了B

方案二:Redux

進(jìn)行狀態(tài)統(tǒng)一管理的類庫(適用于任何技術(shù)體系的項(xiàng)目)

  • 基本流程
    1.createStore(reducer)創(chuàng)建redux公共狀態(tài)管理器
    import {createStore} from 'redux';
    let store = createStore(reducer);
    
    2.設(shè)置管理員函數(shù)reducer(state,action)
    let reducer = (state = {n: 0, m: 0}, action) => {
        switch (action.type) {
            case 'VOTE_SUPPORT':
                state = {...state, n: state.n + 1};
                break;
            case 'VOTE_AGAINST':
                state = {...state, m: state.m + 1};
                break;
        }
        return state;// 只有把最新的STATE返回,原有的狀態(tài)才會(huì)被修改
    };
    
    3.子組件由store.getState()獲取公共狀態(tài)信息,父子的通信可以用組件通信的方案實(shí)現(xiàn)
    let {store: {getState}} = this.props,
        {n, m} = getState();
    this.state = {n, m};
    
    4.store.dispatch()派發(fā)行為通知reducer修改狀態(tài)
    <button className={'btn btn-success'} onClick={() => {
           dispatch({
              type: 'VOTE_SUPPORT'
           });
    }}>支持</button>
    <button className={'btn btn-danger'} onClick={() => {
           dispatch({
               type: 'VOTE_AGAINST'
           });
    }}>反對(duì)</button>
    
    5.子組件通過store.subscribe()把方法追加到事件池中讓其進(jìn)行組件的重新渲染
    componentDidMount() {
          this.props.store.subscribe(() => {
              this.forceUpdate();
          });
      }
    
  • 工程化管理目錄結(jié)構(gòu)
    |-store
    ??|- index.js 創(chuàng)建redux容器
    ??|- action-type.js 宏管理行為派發(fā)標(biāo)識(shí)
    ??|- reducers
    ????|- index.js 各板塊合并后的reducer
    ????|- xxxReducer.js
    ??|- actions
    ????|- index.js 各板塊合并后的action
    ????|- xxxAction.js
  • REACT-REDUX(把REDUX進(jìn)一步封裝,適配REACT項(xiàng)目,讓REDUX操作更簡(jiǎn)潔)
    React提供了自己的一套redux管理體系,其基本流程如下:
    1.工程化管理目錄與redux一致
    2.利用Provider把創(chuàng)建的store掛載到祖先元素的上下文中,供內(nèi)部任何后代組件使用
    render(<Provider store={store}>
        <section className='panel panel-default'>
            <VoteBase/>
            <VoteHandle/>
        </section>
    </Provider>, root);
    
    3.在子組件中通過connect高階組件實(shí)現(xiàn)獲取公共狀態(tài)、重新渲染、行為派發(fā)等一系列流程
    import {connect} from 'react-redux';
    // 把REDUX容器中的狀態(tài)信息遍歷,賦值給當(dāng)前組件的屬性(state)
    let mapStateToProps = state => {
        // state:就是REDUX容器中的狀態(tài)信息
        // return的是啥,就把它掛載到當(dāng)前組件的屬性上(REDUX存儲(chǔ)很多信息,想用啥就返回啥即可)
        return {
            ...state.vote
        };
    };
    
    // 把REDUX中的DISPATCH派發(fā)行為遍歷,也賦值給組件的屬性(ActionCreator)
    let mapDispatchToProps = dispatch => {
        // dispatch:STORE中存儲(chǔ)的DISPATCH方法
        // 返回的是啥,就相當(dāng)于把啥掛載到組件的屬性上(一般會(huì)掛載一些方法,這些方法中完成了DISPATCH派發(fā)任務(wù)操作)
        return {
            init(initData) {
                dispatch(action.vote.init(initData));
            }
        };
    };
    export default connect(mapStateToProps, mapDispatchToProps)(VoteBase);
    
    // 簡(jiǎn)化寫法
    export default connect(state => ({...state.vote}), action.vote)(VoteBase);     // REACT-REDUX幫我們做了一件事情,把ACTION-CREATOR中編寫的方法(返回ACTION對(duì)象的方法),自動(dòng)構(gòu)建成DISPATCH派發(fā)任務(wù)的方法,也就是mapDispatchToProps這種格式
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • [toc] REACT react :1.用來構(gòu)建用戶界面的 JAVASCRIPT 庫2.react 專注于視圖層...
    撥開云霧0521閱讀 1,580評(píng)論 0 1
  • 今天來看一下react組件之間是怎么進(jìn)行通訊的。react推崇的是單向數(shù)據(jù)流,自上而下進(jìn)行數(shù)據(jù)的傳遞,但是由下而上...
    親親qin閱讀 6,077評(píng)論 2 12
  • 看到這篇文章build an image gallery using redux saga,覺得寫的不錯(cuò),長(zhǎng)短也適...
    smartphp閱讀 6,336評(píng)論 1 29
  • 灞陵一別兩千年 英雄已去論英雄 關(guān)廟遍及四海內(nèi) 相府門前舞升平
    吳飾春秋閱讀 738評(píng)論 7 36
  • 揚(yáng)州方圓~~周亮 【知~學(xué)習(xí)】學(xué)習(xí)造價(jià)工程師考試內(nèi)容 《六項(xiàng)精進(jìn)》3遍。累積570遍 《大學(xué)》3遍。累積570遍 ...
    揚(yáng)州方圓__周亮閱讀 75評(píng)論 0 0

友情鏈接更多精彩內(nèi)容