[Vue源码分析]自定义事件原理及事件总线的实现
最近小組有個關(guān)于vue源碼分析的分享會,提前準備一下…
前言:
我們都知道Vue中父組件可以通過 props 向下傳數(shù)據(jù)給子組件;子組件可以通過向$emit觸發(fā)一個事件,在父組件中執(zhí)行回調(diào)函數(shù),從而實現(xiàn)子組件與父組件的通信,如下圖:
從圖可以看到,這種機制兄弟組件之間是通信不了的,假如不借助vuex等庫,如何實現(xiàn)兄弟組件之間的通信?接下來說說事件總線。
事件總線的實現(xiàn)
舉個例子,如圖,建個vue的demo,包含父組件App、子組件Child1及Child2。
(1)main.js
如圖,Vue的原型上定義一個$EventBus,這個$EventBus是一個vue的實例。
(2)App.vue
(3)Child1.vue
(2)Child2.vue
打開瀏覽器,可以看到如圖結(jié)果:
以上例子比較簡單,就不解釋了,可以看到例子就沒有借助vuex,便實現(xiàn)了兄弟組件之間的通信,這是因為我們在Vue原型上定義了一個全局的$EventsBus,各種組件都在共用這個全局的對象,理解其中的原理,首先要對自定義事件做一個分析,接下看看Vue自定義事件實現(xiàn)的相關(guān)源碼。
Vue自定義事件實現(xiàn)原理分析
在vue實例化的時候,會進行很多初始化操作,其中包括eventsMixin這個方法,如圖:
這個方法主要包含四個方法,如圖:
(1)Vue.prototype.$on
可以看到,這個函數(shù)首先判斷傳進來的event是不是一個數(shù)組,如果是數(shù)組,循環(huán)調(diào)用$on把事件及回調(diào)函數(shù)按照事件的名稱event把回調(diào)函數(shù) fn 存儲起來,如代碼中的vm._events[event].push(fn)。
(2)Vue.prototype.$emit
當(dāng)執(zhí)行 vm.$emit(event)的時候,根據(jù)事件名event找到所有的回調(diào)函數(shù),如代碼中的var cbs = vm._events[event],然后遍歷執(zhí)行所有的回調(diào)函數(shù)。
需要注意的是,這里用到了一個toArray(arguments, 1)的方法,是因為第二個開始才是傳遞的參數(shù),所以需要截取出來,如圖:
題外:有興趣可以去了解一下Array.prototype.slice.call()這個方法
(3)vm.$off、vm. $once
這兩個方法比較簡單,就不截圖了,有興趣可以自行去看看。大致是執(zhí)行vm.$off(event,fn) 時會移除指定的事件及回調(diào)函數(shù) ;當(dāng)執(zhí)行 vm.$once(event,fn)時,執(zhí)行的是 vm.$on,但回調(diào)函數(shù)執(zhí)行一次后會通過vm.$off移除事件的回調(diào),這樣就確保了回調(diào)函數(shù)只執(zhí)行一次。
總結(jié)
所自定義的事件添加和刪除用的就是上邊說的幾個方法。子組件中通過$emit派發(fā)事件,父組件中通過$on執(zhí)行回調(diào),進而實現(xiàn)子組件與父組件的通信。事件總線之所以能實現(xiàn)兄弟組件的通信,是因為$emit及$on都定義到了一個全局的$EventBus上。
總結(jié)
以上是生活随笔為你收集整理的[Vue源码分析]自定义事件原理及事件总线的实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 方舟手游羽暴龙刷新点 方舟生存进化
- 下一篇: [Vue源码分析] 模板的编译