当我们使用命令 vue init webpack *** 生成vue项目是,会让我们选择两种模式
- runtime-only
- 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.options.el) 如果有el属性就挂载dom。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END