源碼目錄設(shè)計(jì)
Vue.js 的源碼都在 src 目錄下决乎,其目錄結(jié)構(gòu)如下缘揪。
src├── compiler? ? ? ? # 編譯相關(guān) ├── core? ? ? ? ? ? # 核心代碼 ├── platforms? ? ? # 不同平臺(tái)的支持├── server? ? ? ? ? # 服務(wù)端渲染├── sfc? ? ? ? ? ? #.vue 文件解析├── shared? ? ? ? ? # 共享代碼
compiler
compiler 目錄包含 Vue.js 所有編譯相關(guān)的代碼悉罕。它包括把模板解析成 AST 語(yǔ)法樹(shù)改淑,AST語(yǔ)法樹(shù)優(yōu)化罢绽,代碼生成等功能。
編譯的工作可以在構(gòu)建時(shí)做(可以借助 webpack味榛、vue-loader 等插件)椭坚;也可以在運(yùn)行時(shí)做,使用包含構(gòu)建功能的 Vue.js搏色。編譯是一項(xiàng)耗性能的工作善茎,所以更推薦前者——離線編譯。
core
core 目錄包含了 Vue.js 的核心代碼频轿,包括有內(nèi)置組件垂涯、全局 API 封裝,Vue 實(shí)例化航邢、Obsever耕赘、Virtual DOM、工具函數(shù) Util 等等膳殷。
platform
Vue.js 是一個(gè)跨平臺(tái)的 MVVM 框架操骡,它可以跑在 web 上,也可以配合 weex 跑在 native 客戶端上赚窃。platform 是 Vue.js 的入口册招,2 個(gè)目錄代表 2 個(gè)主要入口,分別打包成運(yùn)行在 web 上和 weex 上的 Vue.js勒极。
server
Vue.js 2.0 支持了服務(wù)端渲染是掰,所有服務(wù)端渲染相關(guān)的邏輯都在這個(gè)目錄下。注意:這部分代碼是跑在服務(wù)端的 Node.js河质,不要和跑在瀏覽器端的 Vue.js 混為一談冀惭。
服務(wù)端渲染主要的工作是把組件渲染為服務(wù)器端的 HTML 字符串,將它們直接發(fā)送到瀏覽器掀鹅,最后將靜態(tài)標(biāo)記"混合"為客戶端上完全交互的應(yīng)用程序。
sfc
通常我們開(kāi)發(fā) Vue.js 都會(huì)借助 webpack 構(gòu)建媒楼, 然后通過(guò) .vue 單文件來(lái)編寫(xiě)組件乐尊。
這個(gè)目錄下的代碼邏輯會(huì)把 .vue 文件內(nèi)容解析成一個(gè) JavaScript 的對(duì)象。
shared
Vue.js 會(huì)定義一些工具方法划址,這里定義的工具方法都是會(huì)被瀏覽器端的 Vue.js 和服務(wù)端的 Vue.js 所共享的扔嵌。
接下來(lái)我們來(lái)找一下Vue的入口文件,我們接下來(lái)的分析都是基于platform為web的環(huán)境下進(jìn)行的分析夺颤,從 package.json 和 config的 的打包配置中里可以看出痢缎,運(yùn)行在web環(huán)境(Runtime only (CommonJS))的入口文件在web/entry-runtime.js下。
Vue入口文件
Vue入口文件目錄 vue/src/core/instance/index.js
// vue/src/core/instance/index.jsimport{initMixin}from'./init'import{stateMixin}from'./state'import{renderMixin}from'./render'import{eventsMixin}from'./events'import{lifecycleMixin}from'./lifecycle'import{warn}from'../util/index'functionVue(options){if(process.env.NODE_ENV!=='production'&&!(thisinstanceofVue)){warn('Vue is a constructor and should be called with the `new` keyword')}this._init(options)}initMixin(Vue)stateMixin(Vue)eventsMixin(Vue)lifecycleMixin(Vue)renderMixin(Vue)exportdefaultVue
采用的是ES5的寫(xiě)法世澜,并不是ES6的Class寫(xiě)法的優(yōu)點(diǎn)独旷,是因?yàn)椋?/p>
1、使用混入Mixin的方式傳入Vue,為Vue的原型prototype上增加方法嵌洼。class難以實(shí)現(xiàn)這種方法
2案疲、此種方式將代碼模塊合理劃分,將擴(kuò)展分散到多個(gè)模塊中去實(shí)現(xiàn)麻养,使得代碼文件不會(huì)過(guò)于龐大褐啡,便于維護(hù)和管理。這個(gè)編程技巧以后可以用于代碼開(kāi)發(fā)實(shí)現(xiàn)中鳖昌。
通過(guò)Mixin增加的原型方法:
// vue/src/core/instance/index.jsinitMixin(Vue) // _initstateMixin(Vue) // $set备畦、$delete、$watcheventsMixin(Vue) // $on许昨、$once萍恕、$off、$emitlifecycleMixin(Vue) // _update车要、$forceUpdate允粤、$destroy、renderMixin(Vue) // $nextTick翼岁、_render
initGlobalAPI
在 vue/src/core/index.js 中类垫,調(diào)用的initGlobalAPI(Vue),是為Vue增加靜態(tài)方法的琅坡,
在路徑 vue/src/core/global-api/ 目錄下的文件中悉患,都是給Vue添加的靜態(tài)方法
比如:
Vue.use// 使用pluginVue.extendVue.mixin Vue.component Vue.directive Vue.filter
有了這些基礎(chǔ)的了解和一步步的跟蹤查找后,我們一步一步找到了new Vue所在的位置榆俺,接下來(lái)我們來(lái)看下new Vue到底做了什么售躁?
new Vue 做了什么
從入口的文件看來(lái),通過(guò)new關(guān)鍵字初始化茴晋,調(diào)用了
// src/core/instance/index.jsthis._init(options)
然后從Mixin增加的原型方法看陪捷,initMixin(Vue),調(diào)用的是為Vue增加的原型方法_init
// src/core/instance/init.jsVue.prototype._init=function(options?:Object){constvm:Component=this........// expose real selfvm._self=vminitLifecycle(vm)initEvents(vm)initRender(vm)callHook(vm,'beforeCreate')initInjections(vm)// resolve injections before data/propsinitState(vm)initProvide(vm)// resolve provide after data/propscallHook(vm,'created')........if(vm.$options.el){vm.$mount(vm.$options.el)}}
所以诺擅,從上面的函數(shù)看來(lái)市袖,new vue所做的事情,就像一個(gè)流程圖一樣展開(kāi)了烁涌,分別是
合并配置
初始化生命周期
初始化事件中心
初始化渲染
調(diào)用beforeCreate鉤子函數(shù)
init injections and reactivity(這個(gè)階段屬性都已注入綁定苍碟,而且被$watch變成reactivity,但是$el還是沒(méi)有生成撮执,也就是DOM沒(méi)有生成)
初始化state狀態(tài)(初始化了data微峰、props、computed抒钱、watcher)
調(diào)用created鉤子函數(shù)蜓肆。
在初始化的最后颜凯,檢測(cè)到如果有 el 屬性,則調(diào)用 vm.$mount 方法掛載 vm症杏,掛載的目標(biāo)就是把模板渲染成最終的 DOM装获。
Vue代碼初始化的主線邏輯非常分明,使得邏輯和流程非常清楚厉颤,這種編程方法值得學(xué)習(xí)穴豫。
最后
現(xiàn)在的部分只是粗略的函數(shù)上講了new Vue的過(guò)程和含義,接下來(lái)的文檔會(huì)繼續(xù)對(duì)Vue的源碼進(jìn)行學(xué)習(xí)和分析逼友,會(huì)接著更細(xì)地分析在生命周期lifecyle下每一個(gè)函數(shù)后面具體所做的事情精肃。
作者:Tiffany_c4df
鏈接:http://www.reibang.com/p/3f4cec40be12
來(lái)源:簡(jiǎn)書(shū)
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)帜乞,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處司抱。