3. 组件通讯(eventHub)

接上一节:https://www.jianshu.com/p/a97f5d408967

这次我们用一个共同继承遗产的例子,通过「eventHub」来完成「组件通讯」。

需求说明:我们在两个「爸爸组件」和四个「儿子组件」中点击消费,然后剩余的金额都能在其他组件中显示,组件通讯达到金额的「同步」。

3. 组件通讯(eventHub)_第1张图片
组件结构图

按照上一节的方法通讯,比如我们在「Son2」点击消费,要通过「回调函数」通过其他组件。如下图,「红色箭头」表示信息传递方向。

3. 组件通讯(eventHub)_第2张图片
上一节「组件通讯」方式.png

现在我们换一种方式,我们“雇佣”一个管家,来专门来管理这笔钱,每一个组件想要消费钱,需要向这个管家报告,这个管家我们称为「eventHub」。「Son2」组件想要消费,「eventHub」得知后并修改金额,然后把新的金额告诉「App」组件,然后从顶端的「App」组件「向下单向」传递信息给其他组件。如下图所示:

3. 组件通讯(eventHub)_第3张图片
单向传递信息.png

代码:

var money = {
  amount: 10000
};



var eventHub = {
  events: {},
  trigger(eventName, data) {
    var fnList = this.events[eventName];
    for(let i = 0; i < fnList.length; i++) {
      fnList[i].call(undefined, data);
    }
  },
  on(eventName, fn) {
    if(!(eventName in this.events)) {
      this.events[eventName] = [];
    }
    
    console.log('this is on')
    this.events[eventName].push(fn);
  }
};

var init = () => {
  // 订阅事件
  eventHub.on('consume', (data) => {
    money.amount -= data;
    // 修改money后再次render
    render();
  })
};

init();


class App extends React.Component {
  constructor() {
    super();
    this.state = {
      money: money
    };
  }
  render() {
    return(
      
); } } class BigDad extends React.Component { constructor(props) { super(props); } render() { return(
大爸: {this.props.money.amount}
); } } class LittleDad extends React.Component { constructor(props) { super(props); } render() { return(
小爸: {this.props.money.amount}
); } } class Son1 extends React.Component { constructor(props) { super(props); } render() { return(
儿子1: {this.props.money.amount}
); } } class Son2 extends React.Component { constructor(props) { super(props); } // 消费 consume() { // 发布事件 eventHub.trigger('consume', 100); } render() { return(
儿子2: {this.props.money.amount}
); } } class Son3 extends React.Component { constructor(props) { super(props); } render() { return(
儿子3: {this.props.money.amount}
); } } class Son4 extends React.Component { constructor(props) { super(props); } render() { return(
儿子4: {this.props.money.amount}
); } } render(); function render() { ReactDOM.render(, document.querySelector('#root')); }

然后我们引入「Redux」来代替「eventHub」。

let createStore = Redux.createStore;



var money = {
  amount: 10000
};



let store = createStore(reducer);

function reducer(state, action) {
  if(typeof state === "undefined") {
    state = money;
  }
  switch (action.type) {
  
    case 'CONSUME':
      return {
        amount: state.amount - action.payload
      }
      
    default:
      return state
  }
}

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      money: money,
    }
  }
  render() {
    return(
      
); } } class BigDad extends React.Component { constructor(props) { super(props); } render() { return(
大爸: {this.props.money.amount}
); } } class LittleDad extends React.Component { constructor(props) { super(props); } render() { return(
小爸: {this.props.money.amount}
); } } class Son1 extends React.Component { constructor(props) { super(props); } render() { return(
儿子1: {this.props.money.amount}
); } } class Son2 extends React.Component { constructor(props) { super(props); } // 消费 consume() { // 发布事件 // eventHub.trigger('consume', 100); // 换用「Redux」 store.dispatch({ type: 'CONSUME', payload: 100}); } render() { return(
儿子2: {this.props.money.amount}
); } } class Son3 extends React.Component { constructor(props) { super(props); } render() { return(
儿子3: {this.props.money.amount}
); } } class Son4 extends React.Component { constructor(props) { super(props); } render() { return(
儿子4: {this.props.money.amount}
); } } store.subscribe(() => { render(); }) render(); function render() { ReactDOM.render(, document.querySelector('#root')); }

如上述代码,其实就是「Redex」中多了几个API来达到跟「eventHub」一样的功能。

// store, 就是保存了所有数据的集合。
// dispatch,就是发送action,跟eventHub.trigger相似
// reducer,就是统一处理数据,跟eventHub.on相似
// subscribe,就是在store的状态有改变的时候,可以进行重新渲染页面

你可能感兴趣的:(3. 组件通讯(eventHub))