vue源码分析之new Vue 发生了什么?

当我们使用命令 vue init webpack *** 生成vue项目是,会让我们选择两种模式

  1. runtime-only
  2. runtime+compiler

我们使用runtime+compiler去分析

下面是一段Vue项目中main.js入口文件的代码:

import Vue from "vue";
import App from "./App.vue";

Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App),
}).$mount("#app");
复制代码
那么打包的入口是哪个文件呢?

下面是 build/config.js的部分代码

  ## config.js
  const aliases = require('./alias')
  const resolve = p => {
      const base = p.split('/')[0]
      if (aliases[base]) {
        return path.resolve(aliases[base], p.slice(base.length + 1))
      } else {
        return path.resolve(__dirname, '../', p)
      }
    }
  const bulids = {
    ***
    // Runtime only (ES Modules). Used by bundlers that support ES Modules,
    // e.g. Rollup & Webpack 2
      'web-runtime-esm': {
        entry: resolve('web/entry-runtime.js'),
        dest: resolve('dist/vue.runtime.esm.js'),
        format: 'es',
        banner
      },
      // Runtime+compiler CommonJS build (ES Modules)
      'web-full-esm': {
        entry: resolve('web/entry-runtime-with-compiler.js'),
        dest: resolve('dist/vue.esm.js'),
        format: 'es',
        alias: { he: './entity-decoder' },
        banner
      },
  }
复制代码
本文分析runtime+compiler模式下

可以看到 当运行在runtime+compiler模式下是入口文件是: web/entry-runtime-with-compiler.js
那么就是src/platforms/web/entry-runtime-with-compiler.js

new Vue发生了什么?

这里只关注new Vue发生什么其他的后面再看。

首先在/src/entries/web-runtime-with-compiler.js入口文件,经过一系列引入后,主要的脉络为以下这些:
## /src/entries/web-runtime-with-compiler.js
import Vue from './runtime/index'
## /src/entries/web/runtime/index.js
## /src/core/index.js
## /src/core/instance/index.js
复制代码

一顿追踪后 发现到/src/core/instance/index这个文件就到头了并且有一系列核心初始化:

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) {
  ***
  this._init(options)
}
//初始化的入口,各种初始化工作
initMixin(Vue)
//数据绑定的核心方法,包括常用的$watch方法
stateMixin(Vue)
//事件的核心方法,包括常用的$on,$off,$emit方法
eventsMixin(Vue)
//生命周期的核心方法
lifecycleMixin(Vue)
// 渲染的核心方法,用来生成render函数以及VNode
renderMixin(Vue)

export default Vue
复制代码

所以当new Vue的时候 就会执行 this._init()这个方法了

所以俺们看看 initMixin这个方法做了什么操作?
export function initMixin (Vue: Class<Component>) {
  Vue.prototype._init = function (options?: Object) {
    const vm: Component = this
    // 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
      )
    }
    // 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')

    if (vm.$options.el) {
      vm.$mount(vm.$options.el)
    }
  }
}
复制代码

一系列包括生命周期、事件、props、attrs,reject,provide等等初始化。 最后执行vm.mount(vm.mount(vm.options.el) 如果有el属性就挂载dom。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享