摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關注公眾號也可以吧原理源碼版之綁定組件自定義事件組件
寫文章不容易,點個贊唄兄弟
專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧
研究基于 Vue版本 【2.5.17】
如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關注公眾號也可以吧
【Vue原理】Event - 源碼版 之 綁定組件自定義事件
組件自定義事件其實是我最感興趣的,我當時花了好多時間去探索的哈哈哈,探索完了之后,發現很簡單的,可以先看下白話版了解下
【Vue原理】Event - 白話版
我當時腦海中就幾個問題,我很想弄懂啊
1、父給子綁定的事件,存放在父組件還是子組件? 2、父給子綁定自定義事件,子組件為什么可以觸發? 3、子組件觸發事件后,是怎么調用綁定的 父組件的方法的?
看看當時做的筆記時間,已經過了好久了啊
筆記看著很混亂,所以下定決心寫文章,寫得詳詳細細的,然自己一眼就明白,而且怕以后自己忘記
首先肯定是為自己服務的,只是順便分享給大家,能幫到別人少走彎路而已哈哈哈
好的,不多說了,馬上進入主題~~看完文章的歡迎到下面投票啊啊啊啊
怎么解析同樣,一個給組件綁定自定義事件的模板
然后template 解析成下面的渲染函數
渲染函數執行,生成這樣的組件外殼VNode
還可以打印組件實例看一下
你可以看到,綁定的自定義事件,存在了 組件外殼VNode的 componentOptions.listeners 中
等下!
渲染函數中,明明把事件解析放在 on 的啊,怎么到 listeners了
這里記錄一下哈
當 _c("test") 執行的時候,因為是組件,所以內部會特別調用 createComponent 去生成組件的VNode
而這個VNode 是外殼VNode
下面的源碼中可以很清楚的看到
1、把 on 賦值給了 listeners
2、listeners 傳給了 VNode 構造函數,保存到了 vnode.componentOptions
function createComponent( Ctor, data, context, children, tag ) { var listeners = data.on; data.on = data.nativeOn; var vnode = new VNode( tag, // 組件名字 data, undefined, undefined, undefined, context, // 下面這個對象就存在 vnode.componentOptions { listeners: listeners, } ); return vnode } function VNode( tag, data, children, text, elm, context, componentOptions ) { this.componentOptions = componentOptions; };
想了解多一點Vnode可以看 VNode - 源碼版
想了解 component 流程的,可以看 Component - 白話版
所以第一個問題得到答案,父給子綁定的事件,存放在子組件中!
怎么綁定好的,模板上的事件已經被解析并保存好了
接下來,就輪到 事件的注冊 showtime
這個事情,發生在創建組件實例的時候
如果你要問,具體是怎么到了創建實例這里的話,你可以看下面兩篇文章,不過看你有沒有這個耐心了(學習的事,能不要耐心嗎)
Component - 源碼版 之 創建組件VNode
Component - 源碼版 之 掛載組件DOM
要不就看白話版吧
Component - 白話版
1、初始化實例組件實例初始化會調用 Vue.prototype._init 沒錯了
然后 _init 會調用一個 initEvents 的東東去進行初始化事件對象,如下
Vue.prototype._init = function(options) { // 增加組件選項,詳情往下看 initInternalComponent(vm,options); initEvents(vm); ....處理選項數據 }
initEvents:沒錯就是我!
2、初始化事件對象initEvent 這個函數做了什么事情呢?
1、給實例上添加一個 _event 對象,用于保存自定義事件
2、獲取到 父組件給 子組件綁定的自定義事件(不懂就接著往下看)
3、調用 updateComponentListeners 開始注冊
function initEvents(vm) { vm._events = Object.create(null); var listeners = vm.$options._parentListeners; if (listeners) { updateComponentListeners(vm, listeners); } }
有個疑惑
_parentListeners 保存的是什么東西?父組件給子組件的事件?
百思不得其解,誒,看到_init 中有一句代碼調用initInternalComponent,也許就是這個函數搞的鬼,我們來看下
3、初始化組件信息function initInternalComponent(vm, options) { .....保存節點等信息 // _parentVnode 是外殼節點 var parentVnode = options._parentVnode; // 保存父組件給子組件關聯的數據 var vcp= parentVnode.componentOptions; vm.$options._parentListeners =vcp.listeners; ....保存渲染函數 }
這個函數的作用是初始化一些組件的信息,包括轉移一些數據
哦~~原來就是通過這個函數偷偷摸摸轉移了 listeners 到了 vm.$option._parentListeners
前面說過【父給子綁定的事件】解析存放在 外殼節點vnode.componentOptions.listeners 中(不明白可以翻到上面的<怎么解析>部分),然后轉移的就是這個 listeners
解決這個疑惑了,好的,我們接著來走 initEvent 剩下的流程把~~
來看下 updateComponentListeners
4、注冊事件function updateComponentListeners( vm, listeners, oldListeners ) { var name, cur, old; for (name in listeners) { cur = listeners[name]; old = oldListeners[name]; // 沒有舊事件,就直接添加新事件 if (typeof old === "undefined") { vm.$on(name, cur); } // 新事件和舊事件不一樣,替換舊事件 else if (cur !== old) { on[name] = cur; } } // 移除舊事件 for (name in oldListeners) { if (typeof listeners[name] === "undefined") { vm.$off(name, oldOn[name]); } } }
就是從他這里開始注冊事件的
似乎沒什么好說的,注意一點
綁定和解綁事件,是直接調用 Vue 的自定義事件方法 $on 和 $off ,大家是不是很熟悉???
沒錯,在這篇文章中說過
【Vue原理】Event - 源碼版 之 自定義事件
這就解釋我們開篇第二個問題了!!!!
為什么我給子組件綁定自定義事件,可以在子組件像下面這樣觸發?
this.$emit("test")
因為 組件綁定的自定義事件 和 Vue 的自定義事件
兩種事件都是使用同一種方法注冊的,所以都存在同樣一個事件對象 【vm._events】 中,是一樣操作的流程
就是這樣的
可以看到組件實例上的 _events
并且知道了第三個問題,怎么調用到父組件的方法?
因為給子組件注冊事件的時候,直接存放父組件的回調,所以觸發事件會調用到父組件的方法
然后你還可以問出一個問題!
為什么子組件觸發事件之后,調用父組件的方法,而父組件的方法上下文對象還是父組件
哈哈,因為 methods 方法已經使用 bind 綁定啦,上下文對象固定了為父組件實例的,所以不管誰調用,怎么調用,都是父組件
詳情可以看這里,
Methods - 源碼版
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/105513.html
摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關注公眾號也可以吧原理源碼版之拼接綁定的事件今天我們 寫文章不容易,點個贊唄兄弟 專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究...
摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關注公眾號也可以吧原理白話版事件是我最感興趣的東西之 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于...
摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關注公眾號也可以吧原理源碼版之綁定組件事件上一篇已經 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于...
摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關注公眾號也可以吧原理源碼版之自定義事件的自定義事件 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于...
摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關注公眾號也可以吧原理源碼版之綁定標簽事件這里的綁定 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于...
閱讀 1711·2021-11-22 12:09
閱讀 1452·2019-08-30 13:22
閱讀 2083·2019-08-29 17:00
閱讀 2635·2019-08-29 16:28
閱讀 2945·2019-08-26 13:51
閱讀 1174·2019-08-26 13:25
閱讀 3238·2019-08-26 12:14
閱讀 3007·2019-08-26 12:14