Vue 2.5 源碼大體概述

前些時間大概看了一下Vue的官方文檔,也大概了解過 Vue 實現(xiàn)數(shù)據(jù)綁定的原理,但是還是想再深入得了解其具體的代碼細節(jié),便抽了些時間來閱讀源碼??戳藗€大概,另外自己水平有限,也只能把自己看懂的分享給大家。

Vue 的源碼用了flow進行類型檢測等工作,真正生產(chǎn)環(huán)境的代碼是 flow編譯而成的,所以在IDE中閱讀代碼時會出現(xiàn)很多代碼錯誤的提示,如果只需要閱讀而不對源碼進行修改和單元測試,則不必過多考慮。需要的話可以去閱讀一下flow這個工具的用法, 這里是官網(wǎng): https://flow.org/

另外,源碼中的語法大都是 ES6 的標準,還運用了很多Object.defineProperty來配置對象成員的 get 和 set 鉤子。

構(gòu)造過程 new Vue({...})

Vue的構(gòu)造器在 src/core/instance/index.js 中,但是在加載Vue這個API的時會先對它進行初始化,代碼位置在 src/core/index.js 中

import Vue from './instance/index'
import { initGlobalAPI } from './global-api/index'
import { isServerRendering } from 'core/util/env'

initGlobalAPI(Vue)

Object.defineProperty(Vue.prototype, '$isServer', {
  get: isServerRendering
})

Object.defineProperty(Vue.prototype, '$ssrContext', {
  get () {
    /* istanbul ignore next */
    return this.$vnode && this.$vnode.ssrContext
  }
})

Vue.version = '__VERSION__'

export default Vue

可以看到這里在 Vue 構(gòu)造器 被導(dǎo)出之前運行了 initGlobalAPI() 來擴展Vue 構(gòu)造器本身的屬性及方法(javascript 作為一個基于原型的 OO 語言, 其中一個函數(shù)也是一個對象,因此是可以有自己的方法和屬性的)。

initGlobalAPI() 在 src/core/global-api/index.js 中

再看 Vue 構(gòu)造器

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

在構(gòu)造器被運行之前,依然運行了一些函數(shù)來初始化Vue 原型的方法,這里很重要,但是在第一篇文章里就不詳述了。

在構(gòu)造 vue 對象時,運行了 _init(options) 函數(shù)來初始化,在src/core/instance/init.js 中

function initMixin (Vue: Class<Component>) {
  Vue.prototype._init = function (options?: Object) {
    const vm: Component = this
    // a uid
    vm._uid = uid++
    ......
    // merge options
    // 在之前對構(gòu)造器本身及其原型進行了擴展,這里進行合并處理
    if (options && options._isComponent) {
      // optimize internal component instantiation
      // since dynamic options merging is pretty slow, and none of the
      // internal component options needs special treatment.
      initInternalComponent(vm, options)
    } else {
      vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
      )
    }
    ......
    vm._self = vm
    initLifecycle(vm) // 初始化生命周期
    initEvents(vm) // 初始化事件及時間處理
    initRender(vm) // 初始化render
    callHook(vm, 'beforeCreate')
    initInjections(vm) // resolve injections before data/props
    initState(vm) // 初始化 data, 的監(jiān)視等
    initProvide(vm) // resolve provide after data/props
    callHook(vm, 'created')
    ......
    if (vm.$options.el) {
      vm.$mount(vm.$options.el) // 掛載
    }
  }
}

在掛載之前先要對生命周期,模板渲染等進行初始化,比較重要的是建立對數(shù)據(jù)的監(jiān)視來實現(xiàn)動態(tài)綁定以在數(shù)據(jù)更改時重新渲染VDOM 并更新DOM。

掛載時要進行模板的編譯和DOM的生成,這一步之后,就順利構(gòu)造完成了。

VDOM

Vue 同 react 一樣, 運用了自己的虛擬DOM來實現(xiàn)DOM的更新,大體可以理解為在數(shù)據(jù)發(fā)生變化時先建立一個虛擬的DOM,并且與之前的虛擬DOM進行比較,最后經(jīng)過diff 之后找到不同并通過 patch 來更行真正的DOM。其優(yōu)點在于避免了大量的DOM操作(因為DOM操作很費資源)。

這里不進行詳細分析,但是推薦給大家一篇文章,里面介紹了諸多框架中數(shù)據(jù)監(jiān)測的實現(xiàn)
http://teropa.info/blog/2015/03/02/change-and-its-detection-in-javascript-frameworks.html

模板編譯

Vue 的模板編譯大體需要經(jīng)過一下幾個步驟

  1. 由template編譯成 ast render 函數(shù)(AST是指抽象語法樹,具體就不說了,因為我也不會)
  2. 運行render 函數(shù),編譯成 vnode(虛擬DOM節(jié)點)
  3. 通過patch更行DOM

而具體的模板編譯和patch都是相對比較復(fù)雜的算法,這里就先不細說(以后可能也細說不了,得看我個人造化了)

數(shù)據(jù)監(jiān)視(數(shù)據(jù)綁定)

Vue 的數(shù)據(jù)綁定主要是通過get 和 set 鉤子來實現(xiàn)的,而鉤子函數(shù)究竟干了什么呢,其實在初始化的過程中建立了一系列的 Observer 對象來監(jiān)視數(shù)據(jù)的變化,在 Observer 中又有 Watcher 對象,負責監(jiān)視到數(shù)據(jù)變化之后的操作(不知道說的對不對,個人理解吧)。Observer 的建立過程中就設(shè)置了諸多get set 鉤子。Watcher則是在掛載時建立(也有可能在其他地方也建立了但是還沒有讀到)。

結(jié)語

以上就是對Vue 2.5 源碼的概述,由于個人水平有限,可能有很多錯誤,希望大家能提出,共同學習。

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

友情鏈接更多精彩內(nèi)容