Vue 原始碼分析之二 Vue Class

2021-09-19 08:19:28 字數 3639 閱讀 9363

這段時間折騰了乙個vue的日期選擇的元件,為了達成我一貫的使用舒服優先原則,我決定使用directive來實現,但是通過這個實現有乙個難點就是我如何把時間選擇的元件插入到dom中,所以問題來了,我是不是又要看vue的原始碼?

vue2.0即將到來,改了一大堆,fragment沒了,所以vue社群中為數不多的元件又有一批不能在2.0中使用,vue的官方外掛程式也是毀得只剩vuex相容,所以在我正在折騰我的元件的時候看到這個訊息我是崩潰的。。。但沒辦法,還是得繼續。希望2.0出來之後官方能完善一下文件,1.0中太多東西根本沒在文件裡提到,比如fragment,比如vue的util方法,這給第三方元件以及外掛程式開發者帶來了無數的瑪法,你只能去看原始碼了,費時費力,剛研究透又來個大更新,我真的想哭/(ㄒoㄒ)/~~

----------回歸正題--------

vue的核心就是他的vue class,component到最終其實也就是乙個vue的例項,包含了一些component獨有的屬性而已,我們來看看這個class做了什麼:

function vue (options)
恩,他呼叫了_init,而在_init裡面就是初始化了一大堆屬性,這些不重要,最重要的是最下面他有這麼一句**:

if (options.el)
這個el是我們在呼叫new vue()時傳入的,即這個vue物件的掛載點,好了,我們找到辦法去動態得把乙個vue的例項掛載到dom裡面了,於是就有了如下**:

const vm = new vue(

})vm.$mount(document.body)

愉快得開啟頁面,等等,為什麼整個頁面上就剩下我是天才這句非常正確的話呢?哦~原來$mount預設是替換整個整個元素的,呵呵噠

那麼我們要如何把節點插入到body裡面呢?這裡有很多辦法,比如你直接呼叫$mount()不傳任何引數,這個時候他不會執行插入操作,然後你把他編譯過的節點(也就是vm.$el)拿出來手動通過dom操作來進行插入,當然我們肯定不能用這麼low的方法o(∩_∩)o~,繼續擼原始碼,很快我們找到了這麼乙個檔案:

// instance/api/dom.js

vue.prototype.$before = function(target, cb, withtransition)

是的,vue的例項自帶一些dom操作的幫助,那麼我們隨便選乙個用就是了,不細說

使用這種方式動態插入的節點會有乙個問題,那就是$el並不是我們真正想要的節點,而是乙個注釋節點,這是為啥?還是看原始碼,我們跟著$mount進去看看他做了什麼:

vue.prototype.$mount = function (el) 

el = query(el)

if (!el)

this._compile(el)

this._initdomhooks()

if (indoc(this.$el)) else

return this

}

顯然我們的el是沒有的,那麼這裡的el就變成了乙個div,然後進行了_compile,再繼續:

// 原始碼太長不貼了

// 檔案位置:instance/internal/lifecycle.js

這裡面他做了乙個el = transclude(el, options),以及this._initelement(el),我們重點看一下this._initelement(el)

vue.prototype._initelement = function (el) 

this._fragment = el

} else

this.$el.__vue__ = this

this._callhook('beforecompile')

}

我們發現這裡的el以及不是之前我們可親的div了,那麼他是什麼呢?我們倒回去看transclude

...

if (options)

if (options.template)

}...

我們是有template的,所以執行了transcludetemplate:

function transcludetemplate (el, options) 

// there are many cases where the instance must

// become a fragment instance: basically anything that

// can create more than 1 root nodes.

if (

// multi-children template

frag.childnodes.length > 1 ||

// non-element template

replacer.nodetype !== 1 ||

// single nested component

tag === 'component' ||

resolveasset(options, 'components', tag) ||

hasbindattr(replacer, 'is') ||

// element directive

resolveasset(options, 'elementdirectives', tag) ||

// for block

replacer.hasattribute('v-for') ||

// if block

replacer.hasattribute('v-if')

) else

} else

} else

}

這邊生成了乙個fragment,好吧,我們最終還是回到了這裡。。。因為這邊返回的是乙個fragment,所以會執行如下**:

if (el instanceof documentfragment)
然後回到剛才的_initelement裡面,this.$el = this._fragmentstart = el.firstchild,額,好吧。。。我表示無力吐槽

那麼回到我們剛才的問題,想要讓$el正確,只需要在new vue()的時候傳入replace: false就行了,但是外面就多包了一層div,怎麼樣都不覺得完美

到這裡我們基本了解了初始化乙個vue物件時的一些方法的執行順序,以及乙個元件如何從字串模板最終到乙個節點的過程,講得比較粗糙,建議有興趣的各位還是自行去看源**吧~

TinyG 韌體原始碼分析之二

2.2 主要後台子任務任務之間的關聯 controller hsm函式中包含多個後台子任務函式,其中 command dispatch實現從串列埠接收各種文字格式指令,配置引數,解析g碼指令產生運動控制指令並寫入mb mpbufferpool t型別 的快取,mp plan hold callbac...

Vue原始碼分析

在開始原始碼分析工作之前,我們在當前篇章做好相應的準備工作,以便更好地展開分析。將原始碼fork到自己的github倉庫中 git clone 自己的github vue 位址 dist 打包之後的結果 examples 示例 src compiler 編譯相關 core vue 核心庫 compo...

STL原始碼分析之二 迭代器

stl原始碼分析之二 迭代器 1.traits程式設計技巧 traits程式設計技法大量運用在 stl實現品中,它利用 內嵌型別 的程式設計技巧與編譯器的 template 引數推導功能,增強 c 未能提供的關於型別認證方面的能力,彌補 c 不為強型別語言的遺憾,例 template struct ...