当组件监听到用户的行为,需要触发一些界面交互的时候,实例与组件之间、组件相互之间就需要进行通信了。Vue里面有两个api可以帮助我们轻松地完成这件事,它们是$on
和$emit
。
实例和组件(parent child)之间的通信
先来看一下我们最后要完成的效果吧。初始状态:
点击按钮以后隐藏文字:
初始代码
<div id="app">
<div class="boxWrapper">
<div>I am your Big Box</div>
</div>
<toggle-btn></toggle-btn>
</div>
Vue.component('toggle-btn', {
template: '<button class="btn btn-info">Toggle Box</button>'
})
var app = new Vue({
el: '#app'
})
我们把按钮做成一个简单的组件,那应该怎么获取按钮监听到的点击事件,传给big box呢?
监听按钮组件上的自定义事件
用户点击的时候,是在toggle-btn
这个组件上触发了事件,所以我们信号的源头,肯定是在它身上。Vue允许我们监听组件上的自定义事件,像这样:
<toggle-btn v-on:toggle-box="toggleBox"></toggle-btn>
这里有几点需要注意的:
自定义的事件,需要用中划线分词,在HTML和JS都是。用驼峰分词是完全没有效果的。
虽然监听的是组件的自定义事件,但后面触发的这个
toggleBox
方法,是在Vue实例上的。这里是监听的是自定义的事件,真正的
click
事件,是在组件内部进行监听(下面会解释)。
所以上面的这行HTML的意思,其实是,当Vue实例监听到组件上自定义的toggle-box
事件被触发,就会执行它的toggleBox
方法。
组件发布信号
被监听的事件有了,这个组件到底要怎么把信号发布出来,让Vue实例监听到呢?我们直接来看下面这段代码。
在组件的内部监听到用户的click
事件后,执行自身的方法,把信号发布出去。
Vue.component('toggle-btn', {
template: '\
<button \
class="btn btn-info" \
v-on:click="emmitToggle">Toggle Box</button>\
',
methods: {
emmitToggle: function() {
// 用户点击之后,发布信号
this.$emit('toggle-box')
}
}
})
完善事件触发的方法
接收到信号以后,我们希望可以toggle文字的显示,最直接的当然是在实例上的data
里面初始化一个showBox
为true
,执行toggleBox
方法的时候对它进行操作。同时,big box里面的文字通过v-show
指令来控制是否显示。
<div class="boxWrapper">
<div v-show="showBox">I am your Big Box</div>
</div>
var app = new Vue({
el: '#app',
data: {
showBox: true
},
methods: {
toggleBox: function() {
this.showBox = !this.showBox
}
}
})
完整的通信流程
组件监听用户行为(我们的例子里是点击)
用户点击,触发组件自身的方法并发布信号(
$emit
):我这边的toggle-box
事件被触发了HTML中的
v-on
指令捕捉到这个信号,执行Vue实例下的toggleBox
方法showBox
的值被修改,v-show
对文字进行隐藏或显示
组件之间的通信
其实$emit
方法是挂在Vue实例下,每一个Vue实例都会有$emit
和$on
方法。所以可以直接把vue实例作为一个event bus,在组件之间进行通信。
这里简单地举个例子。比方说,我们希望点击toggle按钮以后,另外一个组件可以接收到这个信号。
toggle-btn
基本不变,只是改为使用event bus的$emit
方法。listener
中也同样使用event bus的$on
对信号进行监听。
<div id="app">
<listener></listener>
<toggle-btn></toggle-btn>
</div>
var bus = new Vue()
Vue.component('toggle-btn', {
template: '\
<button \
class="btn btn-info" \
v-on:click="emmitToggle">Toggle Box</button>\
',
methods: {
emmitToggle: function() {
// 注意这里使用的是bus,不是this
bus.$emit('toggle-box')
}
}
})
Vue.component('listener', {
template: '<h5>sibling component</h5>',
mounted: function () {
bus.$on('toggle-box', function () {
alert('已经接收到toggle-box信号!')
})
}
})
var app = new Vue({
el: '#app'
})
写在最后
源码地址:https://github.com/levblanc/v...
视频攻略:小的不才,为求一赞,自制 本期视频攻略 在此。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。