new Vue發生了什麼

依然很囧發表於2019-11-06
從入口程式碼開始分析,我們先來分析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初始化主要就幹了幾件事情,合併配置,初始化生命週期,初始化事件,初始化渲染,初始化datapropscomputedwatcher等等。

總結

Vue的初始化邏輯寫的非常清楚,把不同的功能邏輯拆成一些單獨的函式執行讓主線邏輯一目瞭然,這樣的程式設計思想是非常值得借鑑和學習的。由於我們這一章的目標是弄清楚模板和資料如何渲染成最終的DOM,所以各種初始化邏輯我們先不看。在初始化的最後,檢測到如果有
el屬性,則呼叫vm.$mount方法掛載vm,掛載的目標就是把模板渲染成最終的DOM,那麼接下來我們來分析Vue的掛載過程。


相關文章