- options写法:
data选项
createApp({
data(){
return {
foo:1
}
},
}).mount('#demo');
初始化流程:
- 创建
renderer:{render,createApp}
。
- 其中createApp内部定义了
mount()/use()/mixin()/directive()/unmount()/provide()
等app实例方法; - render方法内部会根据vnode执行
patch(container._vnode || null, vnode, container)
新增还是更新;还是unmount(container._vnode, null, null, true)
销毁方法。
- 执行
mount()
方法[mount('#demo')], 在执行mount方法
-
内部创建vnode --
createVnode()
; -
并执行
render(vnode, rootContainer)
方法 --这个方法就是renderder内定义的方法 -
执行
patch()
方法,初始化的时候执行内部的processComponent(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized)
方法,然后再执行mountComponent( n2, container, anchor, parentComponent, parentSuspense, isSVG, optimized )
方法; -
在mountComponent方法内部会
const instance= ComponentInternalInstance()
通过ComponentInternalInstance()
方法获取当前组件实例instance
;然后再调用setupComponent(instance)
方法进行初始化props和slot -- initProps()/initSlots(),由于我这个例子属于有状态的组件,会执行setupStatefulComponent(instance, isSSR)
方法. -
setupStatefulComponent()方法,由于此例子中没有setup就执行
finishComponentSetup(instance, isSSR)
方法. -
finishComponentSetup(instance, isSSR)
方法先const Component = instance.type ;Component.render = compile(Component.template);instance.render = (Component.render)
通过编译器获取render方法,然后if (__FEATURE_OPTIONS_API__) { currentInstance = instance; applyOptions(instance, Component); currentInstance = null}
判断是否有optionsapi执行applyOptions(instance, Component)
方法。 *applyOptions(instance,options)
方法,其中options api有const { // composition mixins, extends: extendsOptions, // state data: dataOptions, computed: computedOptions, methods, watch: watchOptions, provide: provideOptions, inject: injectOptions, // assets components, directives, // lifecycle beforeMount, mounted, beforeUpdate, updated, activated, deactivated, beforeDestroy, beforeUnmount, destroyed, unmounted, render, renderTracked, renderTriggered, errorCaptured } = options
;- 其中beforeMount()执行 onBeforeMount;
- mounted执行 onMounted(mounted.bind(publicThis));
- beforeUpdate执行onBeforeUpdate(beforeUpdate.bind(publicThis));
- updated() 执行onUpdated(updated.bind(publicThis));
- activated() 执行onActivated(activated.bind(publicThis));
- deactivated() 执行onDeactivated(deactivated.bind(publicThis));
- errorCaptured() 执行onErrorCaptured(errorCaptured.bind(publicThis));
- renderTracked() 执行onRenderTracked(renderTracked.bind(publicThis)); 9.renderTriggered()执行onRenderTriggered(renderTriggered.bind(publicThis));
- beforeDestroy() 改成beforeUnmount(); 11.destroyed()改成unmount();
- beforeUnmount()执行onBeforeUnmount(beforeUnmount.bind(publicThis));
- unmounted()执行onUnmounted(unmounted.bind(publicThis));
-
如果有data选项
(dataOptions) { resolveData(instance, dataOptions, publicThis); }
在resolveData()方法内const data = dataFn.call(publicThis, publicThis);先执行data函数,if (!isObject(data)) { __DEV__ && warn(
data() should return an object.) }
判断执行的data返回值是否为对象;再执行reactive(),createReactiveObject( target, false, mutableHandlers, mutableCollectionHandlers )
; 然后instance.data = reactive(data)
;总结
-
createApp()方法内的选项可以存在options api,支持vue2的options api 风格;
-
createApp()内的data选项必须是个函数并且返回值一定为对象,在源码中的resolveData方法中可以获取得到答案,不再支持data为对象的写法;
-
即使写data选项了,内部还是通过reactive(data)方法,把data创建为响应式数据,跟在setup内直接使用reactive(data)一样;
-
通过调用 applyOptions(instance, Component)方法进行处理之前的options api 风格的方法。
-
接下来从开始研究 reactive(data)
-
内部执行
createReactiveObject(target, true,shallowReadonlyHandlers, readonlyCollectionHandlers)
方法; -
在createReactiveObject方法内会判断target是否为对象,是否为只读对象。
const proxyMap = isReadonly ? readonlyMap : reactiveMap
; 所以最外层是proxyMap; -
是否存在,已经存在就return; 先获取target类型,getTargetType(target),内部执行targetTypeMap(toRawType(value))方法
function targetTypeMap(rawType: string) { switch (rawType) { case 'Object': case 'Array': return TargetType.COMMON case 'Map': case 'Set': case 'WeakMap': case 'WeakSet': return TargetType.COLLECTION default: return TargetType.INVALID } }
-
const proxy = new Proxy( target, targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers ) proxyMap.set(target, proxy) return proxy