從入口程式碼開始分析,我們先來分析new Vue背後發生了哪些事情。我們都知道,new關鍵字在Javascript語言中代表例項化是一個物件,而Vue實際上是一個類,類在Javascript中是用Function來實現的,來看一下原始碼,在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只能通過new關鍵字初始化,然後會呼叫this._init方法,該方法在src/core/instance/init.js中定義。
Vue.prototype._init = function (options?: Object) {
const vm: Component = this // a uid
vm._uid = uid++
let startTag, endTag /* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
startTag = `vue-perf-start:${vm._uid}`
endTag = `vue-perf-end:${vm._uid}`
mark(startTag)
}
// a flag to avoid this being observed
vm._isVue = true // merge options
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
) }
/* istanbul ignore else */
if (process.env.NODE_ENV !== 'production') {
initProxy(vm)
} else {
vm._renderProxy = vm
}
// 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')
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
vm._name = formatComponentName(vm, false)
mark(endTag)
measure(`vue ${vm._name} init`, startTag, endTag)
}
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
}複製程式碼
Vue初始化主要就幹了幾件事情,合併配置,初始化生命週期,初始化事件,初始化渲染,初始化data、props、computed、watcher等等。
總結
Vue的初始化邏輯寫的非常清楚,把不同的功能邏輯拆成一些單獨的函式執行,讓主線邏輯一目瞭然,這樣的程式設計思想是非常值得借鑑和學習的。由於我們這一章的目標是弄清楚模板和資料如何渲染成最終的DOM,所以各種初始化邏輯我們先不看。在初始化的最後,檢測到如果有
el屬性,則呼叫vm.$mount方法掛載vm,掛載的目標就是把模板渲染成最終的DOM,那麼接下來我們來分析Vue的掛載過程。