Vue2.0源碼學(xué)習(xí)#0

近來沒什么事,準備把Vue的源碼通讀一遍,2.0中加入了Serve-Side-Render、Virtual-Dom等新特性,看一看實現(xiàn)原理,順便記錄一下學(xué)習(xí)的過程,畢竟好記性不如爛筆頭。

作為源碼解讀系列第一篇文章,先從整個框架的入口開始看吧。Vue使用了部分ES6語法,比如module機制。

import config from './config'
//加載初始全局API
import { initGlobalAPI } from './global-api/index'
//類的初始化入口
import Vue from './instance/index'

initGlobalAPI(Vue)
//在Vue類的原型上定義$isServer屬性,用于判斷是否支持服務(wù)端渲染
//這樣在Vue實例上調(diào)用vue.$isServer就可以知道是否開啟了SSR
//關(guān)于Object.defineProperty,這是一個ES5的方法,可以直接在對象上定義屬性
//Vue的數(shù)據(jù)綁定機制就是用的Object.defineProperty,這也是Vue不支持IE8及以下版本的原因
//將data對象的屬性轉(zhuǎn)成getter和setter,具體原理見http://cn.vuejs.org/guide/reactivity.html
Object.defineProperty(Vue.prototype, '$isServer', {
  get: () => config._isServer
})
//定義Vue版本號
Vue.version = '2.0.0-rc.4'

export default Vue

以下就是config的源碼

//Vue使用了Flow做靜態(tài)類型檢查
//Flow可以在代碼運行前檢查出參數(shù)、返回值、變量等類型異常
//方便我們在代碼運行前進行部分debug
/* @flow */
import { no, noop } from 'shared/util'
export type Config = {
  optionMergeStrategies: { [key: string]: Function };
  silent: boolean;
  devtools: boolean;
  errorHandler: ?Function;
  ignoredElements: ?Array<string>;
  keyCodes: { [key: string]: number };
  // platform
  isReservedTag: (x?: string) => boolean;
  isUnknownElement: (x?: string) => boolean;
  getTagNamespace: (x?: string) => string | void;
  mustUseProp: (x?: string) => boolean;
  // internal
  _assetTypes: Array<string>;
  _lifecycleHooks: Array<string>;
  _maxUpdateCount: number;
  _isServer: boolean;
}
const config: Config = {
  optionMergeStrategies: Object.create(null),
  //是否顯示warning,默認顯示
  silent: false,
  //是否啟動devtool
  devtools: process.env.NODE_ENV !== 'production',
  errorHandler: null,
  ignoredElements: null,
  keyCodes: Object.create(null),
  isReservedTag: no,
  isUnknownElement: no,
  getTagNamespace: noop,
  mustUseProp: no,
 //組件的默認類型
  _assetTypes: [
    'component',
    'directive',
    'filter'
  ],
 //定義組件的各種生命周期
  _lifecycleHooks: [
    'beforeCreate',
    'created',
    'beforeMount',
    'mounted',
    'beforeUpdate',
    'updated',
    'beforeDestroy',
    'destroyed',
    'activated',
    'deactivated'
  ],
 //規(guī)定組件在一次刷新中的最大循環(huán)更新次數(shù)
  _maxUpdateCount: 100,
  //判斷全局環(huán)境是否為server
  _isServer: process.env.VUE_ENV === 'server'
}
export default config

再來看Vue實例由哪些部分構(gòu)成,這部分代碼在src/instance,這個文件夾下有events.js,init.js,lifecycle.js,proxy.js,render.js,state.js`等文件,可以看到,一個Vue instance由這幾部分構(gòu)成。為了將這些模塊組織在一起,Vue使用了Mixin模式。以下是index.js的代碼:

import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'

function Vue (options) {
  this._init(options)
}

initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)

export default Vue

這里的Mixin利用了每個JavaScript對象都有一個原型,通過原型可以繼承更多的屬性,實現(xiàn)Vue類上方法的重用。在每個mixin方法中,將Vue類作為參數(shù)傳遞進去,并在其原型上定義各種內(nèi)置方法。以eventsMixin方法為例:

//為了說明,這里是其簡化版
export function eventsMixin (Vue: Class<Component>) {
  //實現(xiàn)事件綁定的方法,將其添加到原型上
  Vue.prototype.$on = function (event: string, fn: Function): Component {
    const vm: Component = this
   //支持綁定多個事件
    ;(vm._events[event] || (vm._events[event] = [])).push(fn)
    return vm
  }

總結(jié):

  1. Vue中大量使用Object.property,包括利用它生成訪問器,實現(xiàn)數(shù)據(jù)綁定。
  2. Vue使用了Flow做靜態(tài)類型檢查,有助于提前發(fā)現(xiàn)bug
  3. 實現(xiàn)Vue類的過程中使用了Mixin這種設(shè)計模式,基于JavaScript原型繼承的特性,可以方便的擴展Vue實例的功能。

參考鏈接:
Object.defineProperty()
Flow | A Static Type Checker For JavaScript

最后編輯于
?著作權(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ù)。

相關(guān)閱讀更多精彩內(nèi)容

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