故事仍是得從$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;
})));