摘要:的內容如下存放事件名以及對應執行方法。如果是數組的時候,則遞歸,為每一個成員都綁定上方法這里在注冊事件的時候標記值也就是個標志位來表明存在鉤子,而不需要通過哈希表的方法來查找是否有鉤子,這樣做可以減少不必要的開銷,優化性能。
寫在前面
因為對Vue.js很感興趣,而且平時工作的技術棧也是Vue.js,這幾個月花了些時間研究學習了一下Vue.js源碼,并做了總結與輸出。
文章的原地址:https://github.com/answershuto/learnVue。
在學習過程中,為Vue加上了中文的注釋https://github.com/answershuto/learnVue/tree/master/vue-src,希望可以對其他想學習Vue源碼的小伙伴有所幫助。
可能會有理解存在偏差的地方,歡迎提issue指出,共同學習,共同進步。
眾所周知,Vue.js為我們提供了四個事件API,分別是$on](https://cn.vuejs.org/v2/api/#vm-on-event-callback),[$once,$off](https://cn.vuejs.org/v2/api/#vm-off-event-callback),[$emit。
初始化事件初始化事件在vm上創建一個_events對象,用來存放事件。_events的內容如下:
{ eventName: [func1, func2, func3] }
存放事件名以及對應執行方法。
/*初始化事件*/ export function initEvents (vm: Component) { /*在vm上創建一個_events對象,用來存放事件。*/ vm._events = Object.create(null) /*這個bool標志位來表明是否存在鉤子,而不需要通過哈希表的方法來查找是否有鉤子,這樣做可以減少不必要的開銷,優化性能。*/ vm._hasHookEvent = false // init parent attached events /*初始化父組件attach的事件*/ const listeners = vm.$options._parentListeners if (listeners) { updateComponentListeners(vm, listeners) } }$on
$on方法用來在vm實例上監聽一個自定義事件,該事件可用$emit觸發。
Vue.prototype.$on = function (event: string | Array$once, fn: Function): Component { const vm: Component = this /*如果是數組的時候,則遞歸$on,為每一個成員都綁定上方法*/ if (Array.isArray(event)) { for (let i = 0, l = event.length; i < l; i++) { this.$on(event[i], fn) } } else { (vm._events[event] || (vm._events[event] = [])).push(fn) // optimize hook:event cost by using a boolean flag marked at registration // instead of a hash lookup /*這里在注冊事件的時候標記bool值也就是個標志位來表明存在鉤子,而不需要通過哈希表的方法來查找是否有鉤子,這樣做可以減少不必要的開銷,優化性能。*/ if (hookRE.test(event)) { vm._hasHookEvent = true } } return vm }
$once監聽一個只能觸發一次的事件,在觸發以后會自動移除該事件。
Vue.prototype.$once = function (event: string, fn: Function): Component { const vm: Component = this function on () { /*在第一次執行的時候將該事件銷毀*/ vm.$off(event, on) /*執行注冊的方法*/ fn.apply(vm, arguments) } on.fn = fn vm.$on(event, on) return vm }$off
$off用來移除自定義事件
Vue.prototype.$off = function (event?: string | Array$emit, fn?: Function): Component { const vm: Component = this // all /*如果不傳參數則注銷所有事件*/ if (!arguments.length) { vm._events = Object.create(null) return vm } // array of events /*如果event是數組則遞歸注銷事件*/ if (Array.isArray(event)) { for (let i = 0, l = event.length; i < l; i++) { this.$off(event[i], fn) } return vm } // specific event const cbs = vm._events[event] /*Github:https://github.com/answershuto*/ /*本身不存在該事件則直接返回*/ if (!cbs) { return vm } /*如果只傳了event參數則注銷該event方法下的所有方法*/ if (arguments.length === 1) { vm._events[event] = null return vm } // specific handler /*遍歷尋找對應方法并刪除*/ let cb let i = cbs.length while (i--) { cb = cbs[i] if (cb === fn || cb.fn === fn) { cbs.splice(i, 1) break } } return vm }
$emit用來觸發指定的自定義事件。
Vue.prototype.$emit = function (event: string): Component { const vm: Component = this if (process.env.NODE_ENV !== "production") { const lowerCaseEvent = event.toLowerCase() if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) { tip( `Event "${lowerCaseEvent}" is emitted in component ` + `${formatComponentName(vm)} but the handler is registered for "${event}". ` + `Note that HTML attributes are case-insensitive and you cannot use ` + `v-on to listen to camelCase events when using in-DOM templates. ` + `You should probably use "${hyphenate(event)}" instead of "${event}".` ) } } let cbs = vm._events[event] if (cbs) { /*將類數組的對象轉換成數組*/ cbs = cbs.length > 1 ? toArray(cbs) : cbs const args = toArray(arguments, 1) /*遍歷執行*/ for (let i = 0, l = cbs.length; i < l; i++) { cbs[i].apply(vm, args) } } return vm }關于
作者:染陌
Email:answershuto@gmail.com or answershuto@126.com
Github: https://github.com/answershuto
Blog:http://answershuto.github.io/
知乎主頁:https://www.zhihu.com/people/cao-yang-49/activities
知乎專欄:https://zhuanlan.zhihu.com/ranmo
掘金: https://juejin.im/user/58f87ae844d9040069ca7507
osChina:https://my.oschina.net/u/3161824/blog
轉載請注明出處,謝謝。
歡迎關注我的公眾號
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/88728.html
摘要:直接寫了組件機制。今天看了下的關于事件的機制。源碼都是基于最新的。綁定了事件回調函數的。初始化的時候,將中的方法代理到的同時修飾了事件的回調函數。對于事件有兩個底層的處理邏輯。 上一章沒什么經驗。直接寫了組件機制。感覺涉及到的東西非常的多,不是很方便講。今天看了下vue的關于事件的機制。有一些些體會。寫出來。大家一起糾正,分享。源碼都是基于最新的Vue.js v2.3.0。下面我們來看...
摘要:實際上,我在看代碼的過程中順手提交了這個,作者眼明手快,當天就進行了修復,現在最新的代碼里已經不是這個樣子了而且狀態機標識由字符串換成了數字常量,解析更準確的同時執行效率也會更高。 最近饒有興致的又把最新版?Vue.js?的源碼學習了一下,覺得真心不錯,個人覺得 Vue.js 的代碼非常之優雅而且精辟,作者本身可能無 (bu) 意 (xie) 提及這些。那么,就讓我來吧:) 程序結構梳...
摘要:實際上,我在看代碼的過程中順手提交了這個,作者眼明手快,當天就進行了修復,現在最新的代碼里已經不是這個樣子了而且狀態機標識由字符串換成了數字常量,解析更準確的同時執行效率也會更高。 最近饒有興致的又把最新版?Vue.js?的源碼學習了一下,覺得真心不錯,個人覺得 Vue.js 的代碼非常之優雅而且精辟,作者本身可能無 (bu) 意 (xie) 提及這些。那么,就讓我來吧:) 程序結構梳...
摘要:而組件在創建時,又怎么會去調用呢這是由于將自身作為一個插件安裝到了,通過注冊了一個鉤子函數,從而在之后所有的組件創建時都會調用該鉤子函數,給了檢查是否有參數,從而進行初始化的機會。 vue-router 是 Vue.js 官方的路由庫,本著學習的目的,我對 vue-router 的源碼進行了閱讀和分析,分享出來給其他感興趣的同學做個參考吧。 參考 源碼:vuejs/vue-route...
閱讀 2249·2021-11-22 09:34
閱讀 2012·2021-09-22 15:22
閱讀 2015·2019-08-29 15:05
閱讀 2105·2019-08-26 10:43
閱讀 3406·2019-08-26 10:26
閱讀 876·2019-08-23 18:29
閱讀 3518·2019-08-23 16:42
閱讀 1994·2019-08-23 14:46