美文网首页
3. 组件通讯(eventHub)

3. 组件通讯(eventHub)

作者: Jason_Shu | 来源:发表于2019-01-26 21:13 被阅读0次

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

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

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

组件结构图

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

上一节「组件通讯」方式.png

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

单向传递信息.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(
      <div className="app-wrapper">
        <BigDad money={this.state.money}/>
        <LittleDad money={this.state.money}/>
      </div>
    );
  }
}

class BigDad extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return(
      <div className="bigDad">
        <span>大爸:</span>
        <span className="amount">{this.props.money.amount}</span>
        <button>消费</button>
        <Son1 money={this.props.money}/>
        <Son2 money={this.props.money}/>
      </div>
    );
  }
}

class LittleDad extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return(
      <div className="littleDad">
        <span>小爸:</span>
        <span className="amount">{this.props.money.amount}</span>
        <button>消费</button>
        <Son3 money={this.props.money}/>
        <Son4 money={this.props.money}/>
      </div>
    );
  }
}

class Son1 extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return(
      <div className="son1">
        <span>儿子1:</span>
        <span className="amount">{this.props.money.amount}</span>
        <button>消费</button>
      </div>
    );
  }
}

class Son2 extends React.Component {
  constructor(props) {
    super(props);
  }
  
  // 消费
  consume() {
    // 发布事件
    eventHub.trigger('consume', 100);
  }
  
  render() {
    return(
      <div className="son2">
        <span>儿子2:</span>
        <span className="amount">{this.props.money.amount}</span>
        <button onClick={this.consume.bind(this)}>消费</button>
      </div>
    );
  }
}

class Son3 extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return(
      <div className="son3">
        <span>儿子3:</span>
        <span className="amount">{this.props.money.amount}</span>
        <button>消费</button>
      </div>
    );
  }
}

class Son4 extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return(
      <div className="son4">
        <span>儿子4:</span>
        <span className="amount">{this.props.money.amount}</span>
        <button>消费</button>
      </div>
    );
  }
}

render();

function render() {
  ReactDOM.render(<App/>, 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(
      <div className="app-wrapper">
        <BigDad money={this.props.store}/>
        <LittleDad money={this.props.store}/>
      </div>
    );
  }
}

class BigDad extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return(
      <div className="bigDad">
        <span>大爸:</span>
        <span className="amount">{this.props.money.amount}</span>
        <button>消费</button>
        <Son1 money={this.props.money}/>
        <Son2 money={this.props.money}/>
      </div>
    );
  }
}

class LittleDad extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return(
      <div className="littleDad">
        <span>小爸:</span>
        <span className="amount">{this.props.money.amount}</span>
        <button>消费</button>
        <Son3 money={this.props.money}/>
        <Son4 money={this.props.money}/>
      </div>
    );
  }
}

class Son1 extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return(
      <div className="son1">
        <span>儿子1:</span>
        <span className="amount">{this.props.money.amount}</span>
        <button>消费</button>
      </div>
    );
  }
}

class Son2 extends React.Component {
  constructor(props) {
    super(props);
  }
  
  // 消费
  consume() {
    // 发布事件
    // eventHub.trigger('consume', 100);
    
    // 换用「Redux」
    store.dispatch({ type: 'CONSUME', payload: 100});
  }
  
  render() {
    return(
      <div className="son2">
        <span>儿子2:</span>
        <span className="amount">{this.props.money.amount}</span>
        <button onClick={this.consume.bind(this)}>消费</button>
      </div>
    );
  }
}

class Son3 extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return(
      <div className="son3">
        <span>儿子3:</span>
        <span className="amount">{this.props.money.amount}</span>
        <button>消费</button>
      </div>
    );
  }
}

class Son4 extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return(
      <div className="son4">
        <span>儿子4:</span>
        <span className="amount">{this.props.money.amount}</span>
        <button>消费</button>
      </div>
    );
  }
}


store.subscribe(() => {
  render();
})

render();


function render() {
  ReactDOM.render(<App store={store.getState()}/>, document.querySelector('#root'));
}

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

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

相关文章

  • 3. 组件通讯(eventHub)

    接上一节:https://www.jianshu.com/p/a97f5d408967 这次我们用一个共同继承遗产...

  • 高效学习 react 笔记四:redux 和 react-red

    上文我们已经用自己的 eventHub 来完成了任意组件之间的通讯,接下来我们使用 redux 来达到相同的功能。...

  • 高效学习 react 笔记三:组件通讯-eventHub

    1. 任意两个组件之间如何通信 2. 发布订阅模式 3. Redux 就那么回事 上篇文章说到了组件传值可以通过...

  • VUE路由与通讯

    路由的钩子:(即导航守卫) 1.全局, 2.单个路由独享 3.组件级 例如: 5.16组件通讯 组件通讯一、组件:...

  • Vue: EventHub 和 Vue 更配哦

    EventHub 是一个非常重要且常用的东西,在不相关组件通信方面有着很强大的作用。 EventHub 想想如果从...

  • vue非父子组件通信

    1.父组件传递数据给子组件 如果2个组件不是父子组件那么如何通信呢?这时可以通过eventHub来实现通信. 所谓...

  • vue 组件传值

    父组件传值给子组件 父组件传值子组件实时改变3.子组件和父组件通讯直接看代码: 结果: 完成啦,喜欢就留个❤❤吧

  • 组件通信eventHub和Redux

    首先我们要实现上面的结构,根组件App下面有两个子组件大爸和二爸,他们分别都有两个子组件,然后我们要在全局声明一个...

  • 4.组件通信-eventHub

    1.回顾 2.使用eventHub实现通信

  • EventHub-任意组件通信

    什么是EventHub EventHub本质上是基于发布订阅模式来实现的,可以将EventHub理解为发布订阅模式...

网友评论

      本文标题:3. 组件通讯(eventHub)

      本文链接:https://www.haomeiwen.com/subject/qnpvjqtx.html