Vue的初始化过程
一、Vue的构造函数
打开src/core/instance/index.js文件
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'
// Vue的构造函数
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')
}
// 根据options初始化
this._init(options)
}
initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)
export default Vue
Vue的构造函数很简单,仅仅是使用_init函数进行了初始化,然后下面几行Mixin对Vue的构造函数进行了扩展。
-
initMixin:混入了
init函数initMixin函数位于src/core/instance/init.js文件,其作用就是在Vue的原型上添加_init函数。-
_init函数先使用mergeOptions和resolveConstructorOptions函数合并了构造函数默认的optionsvm.$options = mergeOptions( resolveConstructorOptions(vm.constructor), options || {}, vm ) -
然后做了如下操作
/** * 1. 挂载Vue实例的父节点$parent * 2. 将本实例push到父节点的$children中 * 3. 挂载Vue实例的$root节点 * 4. 初始化children, refs, _watcher, _inactive, _directInactive, * _isMounted, _isDestroyed, _isBeingDestroyed的值 */ initLifecycle(vm) /** * 获取父组件中附加到此实例上的事件,然后更新组件的事件监听 */ initEvents(vm) /** * 初始化渲染函数 * 1. 挂载插槽内容,slot和scopedslot到实例上 * 2. 绑定createElement函数到实例上(_c函数和$createElement函数,具体分析后面再说) * 3. 将$attrs和$listeners属性变温响应式属性 */ initRender(vm) /** * 调用beforeCreate钩子函数 */ callHook(vm, 'beforeCreate') // 初始化inject属性 initInjections(vm) // resolve injections before data/props /** * 按照顺序依次 * 1. 初始化props * 2. 初始化methods * 3. 初始化data * 4. 初始化computed * 5. 初始化watch */ initState(vm) // 初始化provide initProvide(vm) // resolve provide after data/props /** * 调用created钩子函数 */ callHook(vm, 'created')- 若el选项存在,通过el挂载Vue实例
if (vm.$options.el) { vm.$mount(vm.$options.el) } -
-
stateMixin:扩展了实例状态相关的属性
- 代理了
$data和$props属性Object.defineProperty(Vue.prototype, '$data', dataDef) Object.defineProperty(Vue.prototype, '$props', propsDef) - 挂载
$set、$delete、$watch函数Vue.prototype.$set = set Vue.prototype.$delete = del Vue.prototype.$watch = function ( expOrFn: string | Function, cb: any, options?: Object ): Function { const vm: Component = this if (isPlainObject(cb)) { return createWatcher(vm, expOrFn, cb, options) } options = options || {} options.user = true const watcher = new Watcher(vm, expOrFn, cb, options) if (options.immediate) { const info = `callback for immediate watcher "${watcher.expression}"` pushTarget() invokeWithErrorHandling(cb, vm, [watcher.value], vm, info) popTarget() } return function unwatchFn () { watcher.teardown() } }
- 代理了
下面的mixin夜做着类似的工作,就不多加赘述了, 具体的分析以后再来搞
- eventsMixin: 扩展事件相关函数
$on$off$emit$once
- lifecycleMixin: 扩展生命周期相关函数
Vue.prototype._update函数$forceUpdate$destroy
- renderMixin: 扩展渲染相关函数
- 扩展运行时的工具函数
- 扩展
$nextTick函数 - 扩展
_render函数
二、说一下_init中的$mount过程
$mount函数实际上就是src/core/instance/lifecycle.js中的mountComponent函数
- 获取要更新的渲染函数
_update - 新建一个Watcher对象,
before中调用beforeUpdate钩子 - 渲染更新完成后调用
mounted钩子 此处涉及到了具体的patch、渲染过程以及响应式原理,先挖个坑,后面再填