React组件通信——Event Bus

使用event bus进行非父子组件间的通信

首先,我们来回顾一下React中组件通信的方式:

  • 父子组件之间的通信,一般是通过props来
    简单来说,就是通过一个将需要通信的变量a定义在父组件中,然后通过props来传递给子组件,如果子组件要更改这个变量,那么父组件就需要定义setA方法,然后也通过props传递给子组件,这样就完成了父子组件之间的通信。

  • 非父子组件之间的通信
    如果两个组件离得近的话,我们可以在两个组件外层嵌套一个父组件,通过父组件共享变量进行通信。这样的话就可以采用上面那个方法来实现了。
    下面是一个todo list的例子:
    todo list包含一个输入组件和一个列表组件,这两个组件需要通信就需要在外层包裹一个TodoComponent,然后维护一个list列表,输入组件调用changeList方法添加事项,列表组件通过this.state.list的变化来重新渲染列表。

export default class TodoComponent extends React.Component{
    constructor(props){
        super(props);
        this.state={
            list:[]
        };


    }
    changeList(last){
        this.setState({
            list: [...this.state.list, last]

    })
    }
    handleRemove(index){
        //console.log(this.state.list.splice(index,1));
        this.state.list.splice(index,1);

        this.setState({
            list:this.state.list
        })
    }


    render(){
        return(
            <div>
                <Inputcomponent changeList={(last)=>this.changeList(last)} list={this.state.list}/>
                <Listcomponent list={this.state.list} handleRemove={(index)=>this.handleRemove(index)}/>
            </div>

        )
    }

}

那么,如果两个组件相隔很远,嵌套了很多组件,则无法采用上面的方法进行通信,这里就需要其他的方式进行通信。
- 如果项目复杂的话,采用redux、mobx进行全局的数据流管理
- 采用发布订阅的Event Bus来进行组件通信


Event Bus

我们可以通过对event的订阅和发布来进行通信,这里举一个栗子:A和B是两个互不相关的组件,A组件的功能是登录,B组件的功能是登录之后显示用户名,这里就需要A组件将用户名传递给B组件。那么我们应该怎么做呢?

  • 在A组件中注册/发布一个type为login的事件;
  • 在B组件中注册一个监听/订阅,监听login事件的触发;
  • 然后当登录的时候login事件触发,然后B组件就可以触发这个事件的回调函数。

那么,我们要如何实现这个Event Bus呢?

class EventBus {
  constructor() {
    this.events = this.events || new Object(); 
  }
}
//首先构造函数需要存储event事件,使用键值对存储
//然后我们需要发布事件,参数是事件的type和需要传递的参数
EventBus.prototype.emit = function(type, ...args) { 
    let e; 
    e = this.events[type];  
    // 查看这个type的event有多少个回调函数,如果有多个需要依次调用。
    if (Array.isArray(e)) {  
        for (let i = 0; i < e.length; i++) {   
            e[i].apply(this, args);    
          }  
   } else {
          e[0].apply(this, args);  
         }  
   };
 //然后我们需要写监听函数,参数是事件type和触发时需要执行的回调函数
 EventBus.prototype.addListener = function(type, fun) { 
       const e = this.events[type]; 

        if (!e) {   //如果从未注册过监听函数,则将函数放入数组存入对应的键名下
         this.events[type]= [fun];
        } else {  //如果注册过,则直接放入
           e.push(fun);
        }
  };
  const eventBus = new EventBus();
  export default eventBus;

到目前为止我们的Event Bus完成了。
然后,我们在login组件中加入

EventBus.emit('login',values.userName)

在需要监听的组件加入

EventBus.addListener('login',(name)=>{
            this.setState({user:name})
        })

这样,登录的用户名就传递到当前组件了。
登录前:侧边栏上显示请登录。
登录前
登陆后:已经将用户名传递到侧边栏组件了。
登陆后

就这样,我们简单的通过Event Bus 实现了跨组件的通信。

猜你喜欢

转载自blog.csdn.net/wengqt/article/details/80114590