前言
在之前,我们学习了父子组件间的通信传值,接下来就看下非父子组件之间是怎样通信。
一、通过单独的事件中心管理组件间的通信
方式一:定义一个空的 Vue 实例作为事件总线
步骤一:定义一个空的 Vue 实例作为事件总线。
var eventHub = new Vue()
我们把这个空的 Vue
实例当作我们组件间通信的中转站,然后在组件中,使用 $emit, $on, $off 分别来分发、监听、取消监听事件,我们就在这些事件中来传递数据,进行组件间通信。
步骤二:定义监听事件
语法:
vm.$on( event, callback )
参数:
{string | Array<string>} event (数组只在 2.2.0+ 中支持)
{Function} callback
用法:
监听当前实例上的自定义事件。事件可以由`vm.$emit`触发。回调函数会接收所有传入事件触发函数的额外参数。
比如我们在user
组件的created
生命周期中监听stateChange
事件,这样在user
组件渲染完毕之后,就会时刻监听stateChange
事件了。
components: {
user: {
template: "<h1>这是user组件</h1>",
created() {
// 步骤二
eventHub.$on('stateChange', function (msg) {
console.log("我是user组件,下面msg打印出来的是login组件的数据")
console.log(msg)
});
},
}
}
步骤三:定义触发事件
语法:
vm.$emit( eventName, […args] )
参数:
{string} eventName
[...args]
用法:
触发当前实例上的事件。附加参数都会传给监听器回调。
比如,我们在组件login
中定义一个按钮,点击这个按钮会触发outLogin
方法,而outLogin
方法内部则会触发stateChange
事件。
结合步骤一,代码如下:
<div id="app">
<login></login>
<user></user>
</div>
<script>
// 步骤一:
var eventHub = new Vue();
var vm = new Vue({
el: '#app',
data: {},
components: {
user: {
template: "<h1>这是user组件</h1>",
created() {
// 步骤二
eventHub.$on('stateChange', function (msg) {
console.log("我是user组件,下面msg打印出来的是login组件的数据")
console.log(msg)
});
},
},
login: {
template: '<input type="button" @click="outLogin" value="我是login组件中的按钮,点我,就会触发stateChange事件">',
methods: {
outLogin() {
// 步骤三:触发stateChange事件
eventHub.$emit('stateChange', '我是login组件的数据');
}
}
}
}
});
</script>
运行效果
可以看到,点击按钮之后,user
组件成功拿到了login
组件的数据,并且user
组件和login
组件并非父子组件的关系。
方式二:在一个vm实例的data内定义一个eventHub: new Vue()
步骤一:在一个vm实例的data内定义一个eventHub: new Vue()
var vm = new Vue({
el: '#app',
data: {
// 步骤一
eventHub: new Vue()
}
});
步骤二:使用this. r o o t . e v e n t H u b . root.eventHub. root.eventHub.on()定义事件监听
我们还在user
组件的created
生命周期中监听stateChange
事件,只不过监听的方式略有不同罢了。
components: {
user: {
template: "<h1>这是user组件</h1>",
created() {
// 步骤二
this.$root.eventHub.$on('stateChange', function(msg) {
console.log("我是user组件,下面msg打印出来的是login组件的数据")
console.log(msg)
})
},
}
}
步骤三:使用this.
r
o
o
t
.
e
v
e
n
t
H
u
b
.
root.eventHub.
root.eventHub.on()定义事件触发
和方式一的步骤三类似,还是在login组件内定义一个按钮,来触发事件,直接来看代码吧。
<div id="app">
<login></login>
<user></user>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
// 步骤一
eventHub: new Vue()
},
components: {
user: {
template: "<h1>这是user组件</h1>",
created() {
// 步骤二
this.$root.eventHub.$on('stateChange', function(msg) {
console.log("我是user组件,下面msg打印出来的是login组件的数据")
console.log(msg)
})
},
},
login: {
template: '<input type="button" @click="outLogin" value="我是login组件中的按钮,点我,就会触发stateChange事件">',
methods: {
outLogin() {
// 步骤三
this.$root.eventHub.$emit('stateChange', '我是login组件的数据');
}
}
}
}
});
</script>
运行效果:
我们可以看到,user组件同样拿到了login组件中的数据。
二、使用vuex
如果对于有很多组件需要通信,或者组件间有较多的共享数据的话,我们可以考虑使用vue官方推荐的vuex
来进行我们的状态管理,多个组件间需要共享的数据,我们都可以放到全局唯一的store
中,不过如果是组件内部的数据,最好不要放到store
中了,毕竟保持store
的简洁也是很重要的,大家如果需要了解更多关于vuex的内容,可以去官方文档看看,这里就不再展开了。
vuex官方中文文档
总结
如有错漏的地方,欢迎指正,谢谢。