用vue也有一兩年了,始終對vue一知半解,不怎么了解內部的執行過程,最近在看vue源碼,還是不少收獲的,其中不乏瀏覽器事件輪詢機制、閉包、設計模式等,還是非常值得一讀。本篇簡要記錄下vue的初始化過程,具體初始化過程及內容的時序如下圖所示:
初始化主要執行了vue-dev\src\core\index.js和vue-dev\src\core\instance\index.js兩個文件,具體執行代碼如下:
vue-dev\src\core\instance\index.js
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) } // 初始化vue _init方法 initMixin(Vue) // 初始化data, prop watch等 stateMixin(Vue) // 初始化發布-訂閱事件模型 eventsMixin(Vue) // 初始化組件生命周期鈎子 lifecycleMixin(Vue) // 初始化nextTick, render renderMixin(Vue)
vue-dev\src\core\index.js
initGlobalAPI(Vue) Object.defineProperty(Vue.prototype, '$isServer', { get: isServerRendering }) Object.defineProperty(Vue.prototype, '$ssrContext', { get () { /* istanbul ignore next */ return this.$vnode && this.$vnode.ssrContext } }) // expose FunctionalRenderContext for ssr runtime helper installation Object.defineProperty(Vue, 'FunctionalRenderContext', { value: FunctionalRenderContext }) Vue.version = '__VERSION__'
在方法initGlobalAPI中,會初始化一切Vue全局的工具方法,像我們常用的全局注冊組件Vue.components,全局注冊指令Vue.directives,set/delete等,具體代碼如下所示:
export function initGlobalAPI (Vue: GlobalAPI) { // config const configDef = {} configDef.get = () => config if (process.env.NODE_ENV !== 'production') { configDef.set = () => { warn( 'Do not replace the Vue.config object, set individual fields instead.' ) } } Object.defineProperty(Vue, 'config', configDef) // exposed util methods. // NOTE: these are not considered part of the public API - avoid relying on // them unless you are aware of the risk. Vue.util = { warn, extend, mergeOptions, defineReactive } Vue.set = set Vue.delete = del Vue.nextTick = nextTick // 2.6 explicit observable API Vue.observable = <T>(obj: T): T => { observe(obj) return obj } // 初始化Vue構造函數的options,初始屬性為components,directives,filters Vue.options = Object.create(null) ASSET_TYPES.forEach(type => { Vue.options[type + 's'] = Object.create(null) }) // this is used to identify the "base" constructor to extend all plain-object // components with in Weex's multi-instance scenarios. // _base屬性 Vue.options._base = Vue extend(Vue.options.components, builtInComponents) // 初始化vue.use api initUse(Vue) // 初始化mixins api initMixin(Vue) // 初始化extend api initExtend(Vue) // 初始化component,directive,filter initAssetRegisters(Vue) }
在首次項目初始化的過程中,會初始化幾個Vue的私有方法,后面在實例化Vue的時候,會經常用到,比如Vue實例上會掛載_init方法,在我們實例化Vue的過程中,實際上調用的是this._init方法,接收的參數options就是我們初始化時的配置項。_render方法是在我們掛載DOM時會被調用,之后會調用_update方法,每次DOM的初始化、更新,都會執行_update方法。
以上為vue初始化過程,主要就是為vue的實例化做一些前置的准備工作,下一篇會介紹vue的實例化過程,如何從基本的配置項到掛載到DOM。