文章出處

前言

組件之間為什么要通信?因為有依賴。
那么,作為React組件,怎么通信?

React官網說,

進行 父-子 通信,可以直接pass props。
進行 子-父 通信,往父組件傳給子組件的函數注入參數。
對于沒有 父-子 關系的組件間的通信,你可以設置你自己的全局事件系統。
詳情見原文翻譯文
那么,到底如何設置全局事件系統呢,React官網沒講。

但十美分的alloyteam的一篇文章卻講了。

該文指出,

  1. 在組件嵌套較深時,純props通信不適用,因為要維護很長的通信鏈。
  2. 在組件很多時,定義很多公共變量也不方便。
  3. 使用Pub/Sub模式有助于簡化多組件通信問題。

那么,市場上哪個Pub/Sub模式實現較好。

在此,我推薦Reflux

還要推薦一篇不錯的Reflux的介紹和基本使用文章
Reflux認為React組件由Store,View,Actions組成。
View即HTML代碼,它是由Store里面的原始數據經過運算得出。
Store里面除了原始數據,還有各種原始數據處理方法。
當View想改變Store的原始數據,可通過Actions。
組件之間的通信,就通過這些原始數據處理方法。
Reflux忽視組件之間的層級關系,不管父-子,子-父等等,皆可通過Store通信。
所以,重點來了(黑板敲三下),我們要理清組件之間的依賴關系。
那么,組件之間有哪些依賴關系呢。
請聽下回分解。
可以劇透的是,
依賴關系無非三種,我依賴你,你依賴我,我們互相依賴,我們互相嘿嘿嘿。
其中,互相依賴這個場景較復雜,示例代碼如下:

// actions1.js
module.exports = Reflux.createActions([
    'getData',
    'setData',
]);

// PageDemo1.js
const reactMixin = require('react-mixin');
const Actions = require('./actions1');
const Store = require('./store1');

class Demo1 extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
        };
    }
    click(){
        Actions.setData("demo1的數據已被設置");
    }
    render() {
        let t = this;
        let data = Store.data;
        if(data == null){
            return null;
        }

        return (
            <div className="demo1">
                <div>{data.name}</div>
                <button onClick={t.click.bind(t)}>設置demo1的數據</button>
                <button onClick={t.click.bind(t)}>設置demo2的數據</button>
            </div>
        );
    }

    componentWillMount() {
    }

    componentDidMount() {
        Actions.getData();
    }

    componentWillReceiveProps(nextProps) {
    }

    shouldComponentUpdate(nextProps, nextState) {
        return true;
    }

    componentWillUpdate(nextProps, nextState) {
    }

    componentDidUpdate(prevProps, prevState) {
    }

    componentWillUnmount() {
    }
}

reactMixin.onClass(Demo1, Reflux.connect(Store));
module.exports = Demo1;

// store1.js
const Actions = require('./actions');
module.exports = Reflux.createStore({
    listenables: [Actions],
    data: null,
    onGetData:function() {
        let t = this;
        t.data = {};
        t.data.name = "demo1";
        t.updateComponent();
    },
    onSetData:function (name) {
        let t = this;
        t.data = {};
        t.data.name = name;
        t.updateComponent();
    },
    updateComponent: function() {
        this.trigger(this.data);
    },

    getInitialState: function() {
        return this.data;
    }
});

// actions2.js
module.exports = Reflux.createActions([
    'getData',
    'setData',
    "setDemo1Data"
]);

// PageDemo2.js
const reactMixin = require('react-mixin');
const Actions = require('./actions2');
const Store = require('./store2');
const Demo1 = require('../demo1');

class Demo2 extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
        };
    }
    click(){
        Actions.setData("demo2的數據已被設置");
    }
    setDemo1Data(){
        Actions.setDemo1Data("demo2設置demo1的數據");
    }
    render() {
        let t = this;
        let data = Store.data;
        if(data == null){
            return null;
        }

        return (
            <div className="demo2">
                <div>{data.name}</div>
                <div>
                    <button onClick={t.click.bind(t)} > 設置demo2的數據</button>
                    <button onClick={t.setDemo1Data.bind(t)} >設置demo1的數據</button>
                </div>
                <Demo1 />
            </div>
        );
    }

    componentWillMount() {
    }

    componentDidMount() {
        Actions.getData();
    }

    componentWillReceiveProps(nextProps) {
    }

    shouldComponentUpdate(nextProps, nextState) {
        return true;
    }

    componentWillUpdate(nextProps, nextState) {
    }

    componentDidUpdate(prevProps, prevState) {
    }

    componentWillUnmount() {
    }
}

reactMixin.onClass(Demo2, Reflux.connect(Store));
ReactDOM.render(<Demo2/>, document.getElementById('App'));
module.exports = Demo2;

// store2.js
const Actions = require('./actions2');
const demo1Store = require('../store1');

module.exports = Reflux.createStore({
    listenables: [Actions],
    data: null,
    onGetData:function() {
        let t = this;
        t.data = {};
        t.data.name = "demo2";
        t.updateComponent();
    },
    onSetData:function (name) {
        let t = this;
        t.data.name = name;
        t.updateComponent();
    },
    onSetDemo1Data:function(name) {
        demo1Store.onSetData(name);
    },
    updateComponent: function() {
        this.trigger(this.data);
    },

    getInitialState: function() {
        return this.data;
    }
});

如上上見,示例代碼又多,又亂.
那么,有什么構建工具能快速搭建開發環境,運行示例代碼。

在此,我推薦nowa

只要你機子上nodejs>=4.0 版本,npm>=3.0 版本,便可以使用nowa。
nowa 的誕生旨在解決以下痛點:

  • 每次下載或新建項目都要安裝一坨開發用的依賴,而這些依賴絕大部分都是重復的,耗時又占空間(僅 babel 的一些插件就一百多兆);
  • 每個項目的構建任務配置在自己項目中維護,不方便統一維護和管理;
  • 構建配置對于很多新手用戶來說還是太繁瑣,迫切需要一個一站式的解決方案;
  • 項目模板的更新依賴于腳手架的發布,頻繁更新用戶體驗不佳;
  • 希望有更流暢的開發體驗;
  • 希望可以在一個地方找到所有常用的工具;
  • 希望能有一個便捷的遠程調試方案;
    ……

好了,至于使用方法大家可進入官網查看,我掩面而逃~~~


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()