VUE中eventBus可以用来进行任何组件之间的通信,我们可以把eventBus当成一个管道,这个管道两端可以接好多组件,两端的任何一个组件都可以进行通信。其实这个管道就是Vue实例,实例中的$on, $off, $emit方法来实现此功能。还是老样子,先通过简单例子看看eventBus怎么用。
<script src="./vue.js"></script>
<div id="app">
<child-comp-1></child-comp-1>
<child-comp-2></child-comp-2>
</div>
<script>
var eventBus = new Vue();
Vue.component('child-comp-1', {
template: "<div></div>",
mounted: function () {
eventBus.$on("event", function(value){
console.log("child-comp-1 receive event: " + value);
});
}
});
Vue.component('child-comp-2', {
template: "<div></div>",
mounted: function () {
eventBus.$emit("event", "here is comp2 msg");
}
});
const app = new Vue({
el: '#app'
});
</script>
我们实例化了一个Vue实例,并赋值给了eventBus全局变量。那么我们就可以在任何地方使用这个全局变量。接下来我们看看这个Vue实例中的$on 和 $emit方法。
function eventsMixin (Vue) {
var hookRE = /^hook:/;
Vue.prototype.$on = function (event, fn) {
var vm = this;
if (Array.isArray(event)) {
for (var i = 0, l = event.length; i < l; i++) {
vm.$on(event[i], fn);
}
} else {
(vm._events[event] || (vm._events[event] = [])).push(fn);
// optimize hook:event cost by using a boolean flag marked at registration
// instead of a hash lookup
if (hookRE.test(event)) {
vm._hasHookEvent = true;
}
}
return vm
};
Vue.prototype.$once = function (event, fn) {
var vm = this;
function on () {
vm.$off(event, on);
fn.apply(vm, arguments);
}
on.fn = fn;
vm.$on(event, on);
return vm
};
Vue.prototype.$off = function (event, fn) {
var vm = this;
// all
if (!arguments.length) {
vm._events = Object.create(null);
return vm
}
// array of events
if (Array.isArray(event)) {
for (var i$1 = 0, l = event.length; i$1 < l; i$1++) {
vm.$off(event[i$1], fn);
}
return vm
}
// specific event
var cbs = vm._events[event];
if (!cbs) {
return vm
}
if (!fn) {
vm._events[event] = null;
return vm
}
// specific handler
var cb;
var i = cbs.length;
while (i--) {
cb = cbs[i];
if (cb === fn || cb.fn === fn) {
cbs.splice(i, 1);
break
}
}
return vm
};
Vue.prototype.$emit = function (event) {
var vm = this;
{
var lowerCaseEvent = event.toLowerCase();
if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
tip(
"Event \"" + lowerCaseEvent + "\" is emitted in component " +
(formatComponentName(vm)) + " but the handler is registered for \"" + event + "\". " +
"Note that HTML attributes are case-insensitive and you cannot use " +
"v-on to listen to camelCase events when using in-DOM templates. " +
"You should probably use \"" + (hyphenate(event)) + "\" instead of \"" + event + "\"."
);
}
}
var cbs = vm._events[event];
if (cbs) {
cbs = cbs.length > 1 ? toArray(cbs) : cbs;
var args = toArray(arguments, 1);
var info = "event handler for \"" + event + "\"";
for (var i = 0, l = cbs.length; i < l; i++) {
invokeWithErrorHandling(cbs[i], vm, args, vm, info);
}
}
return vm
};
}
看看这几个方法,应该都能看的懂。大体说一下,_events是个对象,event作为属性,每个属性值为一个数组。当调用$on方法时就向这个event对应的数组中push方法。当调用$emit方法时就遍历event对应数组中的方法,挨个执行这些方法。