在《「 原创 」Vue源码解析 - Vue究竟是什么?》中知晓了 Vue 实际上就是一个 function,该方法的内容也很简单,就是调用了 _init() 方法,进行初始化操作。
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)
}
在 /src/cor/instance/init.js,定义了 _init 原型方法
export function initMixin (Vue: Class<Component>) {
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)
}
}
}
初始化阶段,主要做了:
合并配置
初始化代理
初始化生命周期
初始化事件
初始化渲染
触发 beforeCreate 钩子
初始化注入器
初始化 data / props / computed / watcher 等
初始化提供者
触发 created 钩子
完成初始化,$options 中存在 el 属性的话,则开始执行实例挂载
小结
new Vue() 之后要干的大事件,都罗列在上面了,非常清晰,具体实现都分到各个功能 / 模块中去了,init 只是集中去调用 / 管理而已。
beforeCreate / created 钩子也是在这里面触发的,需要注意的是 beforeCreate 钩子触发时,initState() 并未执行,也就是说 data / props / computed / watcher 等都还没有初始化,所以并不适合在 beforeCreate 钩子函数内有数据交互的动作,适合做一些 loading 状态。在 created 中就可以对数据进行操作了,我们的异步请求也可以放在这个钩子函数内处理。
接下来就要针对上述事件进行逐个深入分析,在分析过程中可以带着“这些事件是干什么的?”,“在这些事件的实现原理是什么?”,“从原理中窥探作者思想,有哪些是值得借鉴的?”,要形成自己的思考才是最终的目的。