vue.js源碼解讀系列 - Vue的自定義事件機制

最近在解析vue源碼,後期會不斷更新有興趣的能夠關注個人博客vue

關注個人博客:zane的我的博客
git


先看一波使用方式:github

vm.$on 有兩個參數,第一個參數能夠是字符串也能夠是數組,第二個是回調函數

  • 監聽當前實例上的自定義事件。事件能夠由vm.$emit觸發。回調函數會接收全部傳入事件觸發函數的額外參數json

vm.$on('test', function (msg) {
  console.log(msg)
})
vm.$on(['test1','test2'], function (msg) {
  console.log(msg)
})複製代碼

vm.$once 有兩個參數,第一個是時間名稱只能是字符串,第二個是回調函數

  • 監聽一個自定義事件,可是隻觸發一次,在第一次觸發以後移除監聽器
vm.$once('testonce', function (msg) {
  console.log(msg)
})複製代碼

vm.$off 有兩個參數,第一個參數能夠是字符串也能夠是數組,第二個是回調函數

  • 若是沒有提供參數,則移除全部的事件監聽器;
  • 若是隻提供了事件,則移除該事件全部的監聽器;數組

  • 若是同時提供了事件與回調,則只移除這個回調的監聽器。bash

vm.$off()
vm.$off('test')
vm.$off('test1', function (msg) {
  console.log(msg)
})
vm.$off(['test1','test2'], function (msg) {
  console.log(msg)
})複製代碼

vm.$emit 有兩個參數,第一個參數觸發的事件名,第二參數傳遞的參數

  • 觸發當前實例上的事件。附加參數都會傳給監聽器回調。
vm.$emit('test', '觸發自定義事件')複製代碼


下面從源碼來看其實現,vue的自定義事件功能實如今 core/instance/events.js中

一、初始化事件,在vm下掛載_events屬性對象,全部添加的自定義事件都會存放其中


二、$on事件的實現


根據以上分析能夠看出 vm._events 的結構爲:app

vm._events={
    'test':[fn,fn...],
    'test1':[fn,fn...]
}複製代碼


三、$once事件的實現


根據分析得出 $once綁定的事件 vm.events 的結構爲:函數

vm._events={
    'oncetest':[ 
          function on(){
              vm.$off(event,on)
              fn.apply(vm,arguments)
          } ,
          ...
     ]
}複製代碼


四、$off事件的實現


一一的實現了下面的這三點:this

  • 若是沒有提供參數,則移除全部的事件監聽器;spa

  • 若是隻提供了事件,則移除該事件全部的監聽器;

  • 若是同時提供了事件與回調,則只移除這個回調的監聽器。


五、$emit事件的實現



白話描述:匹配到json中相關key值的value,這個value先轉換成真正的數組,再循環遍歷數組,傳入給的參數執行數組中的每一個函數。


總結:

整個自定義事件就是在vm下掛載一個_events的Object對象,能夠理解爲一個json,其中json的key值就是自定義事件的名稱,一個key值可能對應着多個自定義事件,所以json中每一個key對應的value都是一個數組,每次執行事件監聽都會向數組中push相關的函數,最終經過$emit函數傳入的參數,匹配到json中相應的key,val值,從而使用給定的參數執行數組中的函數。

最終的vm._events能夠是這樣的值:

vm._events={
    'test1':[fn,fn,fn],
    'test2':[fn],
    'oncetest':[ 
          function on(){
              vm.$off(event,on)
              fn.apply(vm,arguments)
          },
          ... 
     ],
     ...
}複製代碼

vue中自定義事件的主要做用是組件間的通訊,由於_events對象最終掛載在Vue的實例上,所以每一個組件都可以訪問到vm._events的值,也能向其中push相關的訂閱函數。

最典型的用法就是vue組件間的組件通訊,父組件使用 :foo.sync , 子組件使用 this.$emit('update:foo', option) 進行雙向通訊,若是你有看過vue的源碼就會發現實際上,:foo.sync 最終會綁定一個 'update:foo' 的事件。

<comp :foo.sync="bar"></comp>
會被拓展爲
<comp :foo="bar" @update:foo="val => bar = val"></comp>複製代碼




關注個人博客:zane的我的博客

原文地址:vue.js源碼解讀系列 - Vue的自定義事件機制

相關文章
相關標籤/搜索