故事仍是得从$emit提及,某一天翻文档的时候看到$emit的说明javascript
触发当前实例上的事件?就是自身组件上的事件呗,在父子组件通讯中,父组件经过props传递给子组件数据(高阶组件能够用provide和inject),因为这是单向数据流,为了保证复用组件的的时候出现数据错乱。vue
那么只能经过在子组件里面去触发一个事件,来让父组件本身更新数据。java
那么问题来了,$emit不是说好的触发当前实例上的事件吗?那是怎么去能触发父组件数据更新的呢?难道父组件里也能$on对应的事件???git
其实不是的,看下面这个示例github
<div id="app1">
<m-area :v="value" @do="pAdd"></m-area>
</div>
<script src="js/vue.js"></script>
<script>
Vue.component('mArea', {
props: ['v'],
template: `
<div>
<button @click="add">{{v}}</button>
</div>
`,
methods: {
add() {
this.$emit('do');
console.log(this.v)
}
}
});
let app1 = new Vue({
el: '#app1',
data: {
value: 1
},
methods: {
pAdd() {
this.value++;
},
mouseover() {
console.log(this.value);
}
}
});
</script>
其实Button 的add方法是只触发了它自身的do事件,可是app
<div id="app1">
<m-area :v="value" @do="pAdd"></m-area>
</div>
mArea标签就是该组件啊,do事件是只触发了自身的事件,可是m-area标签是暴露在父组件里的,看看pAdd方法,它是父组件的mthods里的一个方法。由此恰好触发自身组件事件的时候,又触发了父组件里的一个方法,数据能够传参,最终达到更新父组件数据的目的。ide
接下来讲说eventBusthis
通常都是建立一个bus.js,而后 export default new Vue()spa
其实背后就是个原理,经过bus.$emit而后涉及到原型链查找,至关于直接是针对于根组件App执行的$emit和$on,站在一个上帝视角,最顶层的组件上,就能造成一个事件总线,这样不一样的兄弟组件之间就能进行通讯了。prototype
顺即可以看看vue-bus这个插件的源码,其实也是这么实现的,而后是经过更改get,改了一下调用属性方法的别名而已,而后挂到vue.prototype上,方便全局调用。
/**
* vue-bus v1.1.0
* https://github.com/yangmingshan/vue-bus
* @license MIT
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.VueBus = factory());
}(this, (function () { 'use strict';
function VueBus(Vue) {
var bus = new Vue();
Object.defineProperties(bus, {
on: {
get: function get() {
return this.$on
}
},
once: {
get: function get() {
return this.$once
}
},
off: {
get: function get() {
return this.$off
}
},
emit: {
get: function get() {
return this.$emit
}
}
});
Vue.bus = bus;
Object.defineProperty(Vue.prototype, '$bus', {
get: function get() {
return bus
}
});
}
if (typeof window !== 'undefined' && window.Vue) {
window.Vue.use(VueBus);
}
return VueBus;
})));