前面我们讲到了_init函数的执行流程,简单回顾下:
- 初始化生命周期-initLifecycle
- 初始化事件-initEvents
- 初始化渲染函数-initRender
- 调用钩子函数-beforeCreate
- 初始化依赖注入-initInjections
- 初始化状态信息-initState
- 初始化依赖提供-initProvide
- 调用钩子函数-created
一共经过上面8步,init函数执行完成,开始mount渲染。
初始化状态信息
本章咱们主要讲解initState函数的处理过程,咱们先看下init的主函数
function initState(vm: Component) {
vm._watchers = []
const opts = vm.$options
if (opts.props) {
initProps(vm, opts.props)
}
if (opts.methods) {
initMethods(vm, opts.methods)
}
if (opts.data) {
initData(vm)
} else {
observe(vm._data = {
}, true /* asRootData */)
}
if (opts.computed) {
initComputed(vm, opts.computed)
}
if (opts.watch && opts.watch !== nativeWatch) {
initWatch(vm, opts.watch)
}
}
看上面代码,先声明了一个_watchers的空数组;然后依次判断传递进来的options是否包含系列参数;依次执行initProps、initMethods、initData、initComputed、initWatch。
initProps
initProps函数主要是处理传进来的props对象,但是这个props对象是在上一篇文章中讲到的normalizeProps函数处理后的对象,不是传递进来的原对象。来看下initProps的代码:
function initProps(vm: Component, propsOptions: Object) {
const propsData = vm.$options.propsData || {
}
const props = vm._props = {
}
const keys = vm.$options._propKeys = []
const isRoot = !vm.$parent
if (!isRoot) {
toggleObserving(false)
}
for (const key in propsOptions) {
keys.push(key)
const value = validateProp(key, propsOptions, propsData, vm)
defineReactive(props, key, value)
if (!(key in vm)) {
proxy(vm, `_props`, key)
}
}
toggleObserving(true)
}
上面代码解读:
- 第一步获取了propsData;
- 第二步给当前实例添加了_props属性,新增了一个props引用,指向了_props属性;
- 第三步给当前实例增加了_propKeys属性,新增了一个keys的引用,指向了_propKeys属性;
- 第四步判断了是否需要进行监听;
- 遍历normalizeProps函数处理后的对象propsOptions;
-
- 存储key
-
- 校验props格式
-
- 为当前key定义响应式的属性:defineReactive
-
- 把当前key的访问方式提高到实例上面:proxy,即可以vm.name来访问vm._props.name
Vue3核心源码视频讲解:进入学习
function proxy(target: Object, sourceKey: string, key: