Vue源碼分析(一) : new Vue() 做了什么

Vue源碼分析(一) : new Vue() 做了什么

author: @TiffanysBear

在了解new Vue做了什么之前,我們先對Vue源碼做一些基礎的了解,如果你已經對基礎的源碼目錄設計等有基礎的了解的話,可以跳過下面這部分。

源碼目錄設計

Vue.js 的源碼都在 src 目錄下,其目錄結構如下。

src
├── compiler        # 編譯相關 
├── core            # 核心代碼 
├── platforms       # 不同平臺的支持
├── server          # 服務端渲染
├── sfc             # .vue 文件解析
├── shared          # 共享代碼

compiler

compiler 目錄包含 Vue.js 所有編譯相關的代碼。它包括把模板解析成 AST 語法樹,AST語法樹優(yōu)化,代碼生成等功能。

編譯的工作可以在構建時做(可以借助 webpack、vue-loader 等插件);也可以在運行時做,使用包含構建功能的 Vue.js。編譯是一項耗性能的工作,所以更推薦前者——離線編譯。

core

core 目錄包含了 Vue.js 的核心代碼,包括有內置組件、全局 API 封裝,Vue 實例化、Obsever、Virtual DOM、工具函數 Util 等等。

platform

Vue.js 是一個跨平臺的 MVVM 框架,它可以跑在 web 上,也可以配合 weex 跑在 native 客戶端上。platform 是 Vue.js 的入口,2 個目錄代表 2 個主要入口,分別打包成運行在 web 上和 weex 上的 Vue.js。

server

Vue.js 2.0 支持了服務端渲染,所有服務端渲染相關的邏輯都在這個目錄下。注意:這部分代碼是跑在服務端的 Node.js,不要和跑在瀏覽器端的 Vue.js 混為一談。

服務端渲染主要的工作是把組件渲染為服務器端的 HTML 字符串,將它們直接發(fā)送到瀏覽器,最后將靜態(tài)標記"混合"為客戶端上完全交互的應用程序。

sfc

通常我們開發(fā) Vue.js 都會借助 webpack 構建, 然后通過 .vue 單文件來編寫組件。

這個目錄下的代碼邏輯會把 .vue 文件內容解析成一個 JavaScript 的對象。

shared

Vue.js 會定義一些工具方法,這里定義的工具方法都是會被瀏覽器端的 Vue.js 和服務端的 Vue.js 所共享的。

接下來我們來找一下Vue的入口文件,我們接下來的分析都是基于platform為web的環(huán)境下進行的分析,從 package.json 和 config的 的打包配置中里可以看出,運行在web環(huán)境 (Runtime only (CommonJS))的入口文件在 web/entry-runtime.js下。

Vue入口文件

Vue入口文件目錄 vue/src/core/instance/index.js

// vue/src/core/instance/index.js
import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'
import { warn } from '../util/index'

function Vue (options) {
  if (process.env.NODE_ENV !== 'production' &&
    !(this instanceof Vue)
  ) {
    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)

export default Vue

采用的是ES5的寫法,并不是ES6的Class寫法的優(yōu)點,是因為:

1、使用混入Mixin的方式傳入Vue,為Vue的原型prototype上增加方法。class難以實現這種方法
2、此種方式將代碼模塊合理劃分,將擴展分散到多個模塊中去實現,使得代碼文件不會過于龐大,便于維護和管理。這個編程技巧以后可以用于代碼開發(fā)實現中。

通過Mixin增加的原型方法:

// vue/src/core/instance/index.js
initMixin(Vue) // _init
stateMixin(Vue) // $set、$delete、$watch
eventsMixin(Vue) // $on、$once、$off、$emit
lifecycleMixin(Vue) // _update、$forceUpdate、$destroy、
renderMixin(Vue) // $nextTick、_render 


initGlobalAPI

在 vue/src/core/index.js 中,調用的initGlobalAPI(Vue),是為Vue增加靜態(tài)方法的,

在路徑 vue/src/core/global-api/ 目錄下的文件中,都是給Vue添加的靜態(tài)方法

比如:

Vue.use // 使用plugin
Vue.extend
Vue.mixin 
Vue.component 
Vue.directive 
Vue.filter

有了這些基礎的了解和一步步的跟蹤查找后,我們一步一步找到了 new Vue 所在的位置,接下來我們來看下 new Vue 到底做了什么?

new Vue 做了什么

從入口的文件看來,通過new關鍵字初始化,調用了

// src/core/instance/index.js

this._init(options)

然后從Mixin增加的原型方法看,initMixin(Vue),調用的是為Vue增加的原型方法_init

// src/core/instance/init.js

Vue.prototype._init = function (options?: Object) {
    const vm: Component = this
    ....
    ....
    // expose real self
    vm._self = vm
    initLifecycle(vm)
    initEvents(vm)
    initRender(vm)
    callHook(vm, 'beforeCreate')
    initInjections(vm) // resolve injections before data/props
    initState(vm)
    initProvide(vm) // resolve provide after data/props
    callHook(vm, 'created')
    
    ....
    ....
    
    if (vm.$options.el) {
      vm.$mount(vm.$options.el)
    }
}


所以,從上面的函數看來,new vue所做的事情,就像一個流程圖一樣展開了,分別是

  • 合并配置
  • 初始化生命周期
  • 初始化事件中心
  • 初始化渲染
  • 調用 beforeCreate 鉤子函數
  • init injections and reactivity(這個階段屬性都已注入綁定,而且被 $watch 變成reactivity,但是 $el 還是沒有生成,也就是DOM沒有生成)
  • 初始化state狀態(tài)(初始化了data、props、computed、watcher)
  • 調用created鉤子函數。

在初始化的最后,檢測到如果有 el 屬性,則調用 vm.$mount 方法掛載 vm,掛載的目標就是把模板渲染成最終的 DOM。

Vue代碼初始化的主線邏輯非常分明,使得邏輯和流程非常清楚,這種編程方法值得學習。

最后

現在的部分只是粗略的函數上講了 new Vue 的過程和含義,接下來的文檔會繼續(xù)對Vue的源碼進行學習和分析,會接著更細地分析在生命周期lifecyle下每一個函數后面具體所做的事情。

?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 從一個能夠積極樂觀看待生活的(青年?少年?)到現在毫無斗志如同一張衛(wèi)生紙的廢柴。 只需要三個月的時間 我終于也變成...
    Dawning閱讀 1,078評論 0 0
  • 圣誕節(jié)買了《不一樣的卡梅拉》這本書送給兒子,故事講的是一直雞從“下蛋、下蛋還是下蛋,生活應該有更好玩的事情”這個想...
    大鵬_9a76閱讀 333評論 1 0
  • 感受:通過主干在紙上記憶很快會背了開心,但是在電腦上就亂了,好幾句又要記還要主次,錯了不少。 發(fā)現:通常單句就適合...
    小燕l(xiāng)ucky閱讀 146評論 0 1
  • 我把思念裝進瓶子里 疊成帆船的樣子 蓋上木塞 放到大海里 劃向你的方向 它會帶著我的心 告訴你我的思念 相信你能看...
    雙魚座cy閱讀 709評論 8 12

友情鏈接更多精彩內容