1. 程式人生 > >從$emit 到 父子組件通信 再到 eventBus

從$emit 到 父子組件通信 再到 eventBus

win fun prop () undefined cli methods 執行 更新數據

故事還是得從$emit說起,某一天翻文檔的時候看到$emit的說明

技術分享圖片

觸發當前實例上的事件?就是自身組件上的事件唄,在父子組件通信中,父組件通過props傳遞給子組件數據(高階組件可以用provide和inject),由於這是單向數據流,為了保證復用組件的的時候出現數據錯亂。

那麽只能通過在子組件裏面去觸發一個事件,來讓父組件自己更新數據。

那麽問題來了,$emit不是說好的觸發當前實例上的事件嗎?那是怎麽去能觸發父組件數據更新的呢?難道父組件裏也能$on對應的事件???

其實不是的,看下面這個示例

    <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事件,但是

 <div id="app1">
        <m-area :v="value" @do="pAdd"></m-area>
 </div>

mArea標簽就是該組件啊,do事件是只觸發了自身的事件,但是m-area標簽是暴露在父組件裏的,看看pAdd方法,它是父組件的mthods裏的一個方法。由此剛好觸發自身組件事件的時候,又觸發了父組件裏的一個方法,數據可以傳參,最終達到更新父組件數據的目的。

接下來說說eventBus

一般都是創建一個bus.js,然後 export default new Vue()

其實背後就是個原理,通過bus.$emit然後涉及到原型鏈查找,相當於直接是針對於根組件App執行的$emit和$on,站在一個上帝視角,最頂層的組件上,就能形成一個事件總線,這樣不同的兄弟組件之間就能進行通信了。

順便可以看看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;

})));

  

  

  

  

從$emit 到 父子組件通信 再到 eventBus