在使用Vue的过程中,将一个较大的页面拆分为几个组件能更好的进行解耦和代码的复用,但是不同的组件之间通常会进行信息的传递,如何进行消息的传递?通常,整个Vue页面是一个大的父组件,父组件中包含许多子组件,由父组件向子组件传递消息的时候,子组件可以使用props属性来接收从父组件传递的数据或函数等相关信息。但是两个兄弟组件之间不能直接使用props属性进行通信,如果使用父组件间接的使用较为麻烦,可以考虑使用事件总线来进行通信,不仅可以用于兄弟组件之间,任意两个组件都可以进行消息的传递。
一、使用props进行通信
例如有以下的组件,root是整个的父组件App,下面有三个子组件,todos是父组件中data的数据,然后将这个数据转递给MyList、MyFooter组件,checkTodo、deleteTodo是父组件methods中的函数,子组件接收到之后,可以通过函数修改父组件的相关数据,完成组件间的通信。
<div id="root">
<MyHeader @addTodo="addTodo"></MyHeader>
<MyList :todos="todos" :checkTodo="checkTodo" :deleteTodo="deleteTodo"></MyList>
<MyFooter :todos="todos" :checkAllTodo="checkAllTodo"></MyFooter>
</div>
下面以MyFooter为例,props接收到父组件传递的信息,在methods中的方法中调用传递来的函数,实现对父组件数据的修改,可以进行向父组件传递信息。
name:'MyFooter',
props:['todos','checkAllTodo','clearAllTodo'],
computed:{
total(){
return this.todos.length
},
doneTotal(){
return this.todos.reduce((pre,current)=>pre+(current.done? 1 : 0),0)
},
isAll(){
return this.total===this.doneTotal && this.total!==0
}
},
methods: {
checkAll(e){
this.checkAllTodo(e.target.checked)
},
clearAll(){
this.clearAllTodo()
}
},
二、使用事件总线的方式
使用props的方式传递较为麻烦,如果需要向孙子组件传递(子组件的子组件),则需要进行两次的props。如果是兄弟组件间的通信,则需要借助共同的父组件来进行props的通信。所以引入了事件总线,具体的原理不再解释,直接解释如何进行使用。
首先是两个兄弟组件SchoolInfo和StudentInfo,这两个兄弟组件同属于父组件App,如果这两个组件想要进行通信,不能直接进行,这里使用事件总线的方式。
<div class="student">
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<button @click="sendStudentName">把学生名给School组件</button>
</div>
<div class="school">
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
为了使用事件总线,需要再main.js中,进行配置,安装全局事件总线。
new Vue({
el:'#app',
render: h => h(App),
beforeCreate() {
Vue.prototype.$bus = this //安装全局事件总线
},
})
这个例子中StudentInfo组件想通过点击按钮把学生姓名传递给Schoo组件。看一下School中的相关代码:
mounted() {
this.$bus.$on('hello',(data)=>{
console.log('我是School组件,收到了数据',data)
})
},
beforeDestroy() {
this.$bus.$off('hello')
}
代码中mounted,执行全局消息组件的挂载,当有其他事件触发了该事件(例子中的hello事件)时候,控制台打印输出语句并将传递的消息打印出来。并在结束的时候进行事件的解绑。
Student组件中的代码如下:
methods: {
sendStudentName(){
this.$bus.$emit('hello',this.name)
}
},
代码中,methods中实现了sendStudentName函数,点击事件可以触发这个函数,函数中执行事件的分发,使用emit,并将结果name传递过去,使得School组件可以接收到。
三、总结
使用事件总线之前首先再main.js中进行总线的挂载,然后,在需要接收消息的组件中执行this.$bus.$on()进行事件的绑定,在发送消息的组件中执行this.$bus.$emit()进行事件的分发,就可以完成总线中的消息传递。