这一章我们来解决前面留下的部分todo
getExposeProxy方法 路径: core\packages\runtime-core\src\component.ts
export function getExposeProxy(instance: ComponentInternalInstance) {
// 判断exposed是否存在
if (instance.exposed) {
//todo To: 返回通过proxyRefs 和markRaw处理的
return (
instance.exposeProxy ||
(instance.exposeProxy = new Proxy(proxyRefs(markRaw(instance.exposed)), {
get(target, key: string) {
if (key in target) {
return target[key]
} else if (key in publicPropertiesMap) {
return publicPropertiesMap[key](instance)
}
}
}))
)
}
}
才看一步,我们又看到了proxyRefs和markRaw(涉及响应式),因此留下todo
createSetupContext方法 路径: core\packages\runtime-core\src\component.ts
export function createSetupContext(
instance: ComponentInternalInstance
): SetupContext {
// 初始化expose
const expose: SetupContext['expose'] = exposed => {
instance.exposed = exposed || {}
}
let attrs: Data
if (__DEV__) {
} else {
// 返回包含attrs slots emit expose的对象
return {
get attrs() {
return attrs || (attrs = createAttrsProxy(instance))
},
slots: instance.slots,
emit: instance.emit,
expose
}
}
}
createSetupContext方法做了什么?
功能: 返回一个包含attrs slots emit expose的对象,也就是我们使用的setup的第二个参数
对这个方法的分析我都写在了注释上,因为涉及太多的方法跳转
这一步的注释在 初始化setupContext
initProps方法 路径: core\packages\runtime-core\src\componentProps.ts
export function initProps(
instance: ComponentInternalInstance,
rawProps: Data | null,
isStateful: number, // result of bitwise flag comparison
isSSR = false
) {
const props: Data = {}
const attrs: Data = {}
def(attrs, InternalObjectKey, 1)
instance.propsDefaults = Object.create(null)
setFullProps(instance, rawProps, props, attrs)
// ensure all declared prop keys are present
for (const key in instance.propsOptions[0]) {
if (!(key in props)) {
props[key] = undefined
}
}
if (isStateful) {
// stateful
instance.props = isSSR ? props : shallowReactive(props)
} else {
if (!instance.type.props) {
// functional w/ optional props, props === attrs
instance.props = attrs
} else {
// functional w/ declared props
instance.props = props
}
}
instance.attrs = attrs
}
initProps方法做了什么?
功能: 初始化并拆分props、attrs,并对default做了处理,prop大小写进行了处理
对这个方法的分析我都写在了注释上(和initSlots在一起),因为涉及太多的方法跳转
initSlots方法 路径: core\packages\runtime-core\src\componentSlots.ts
export const initSlots = (
instance: ComponentInternalInstance,
children: VNodeNormalizedChildren
) => {
if (instance.vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) {
const type = (children as RawSlots)._
if (type) {
// users can get the shallow readonly version of the slots object through `this.$slots`,
// we should avoid the proxy object polluting the slots of the internal instance
instance.slots = toRaw(children as InternalSlots)
// make compiler marker non-enumerable
def(children as InternalSlots, '_', type)
} else {
normalizeObjectSlots(
children as RawSlots,
(instance.slots = {}),
instance
)
}
} else {
instance.slots = {}
if (children) {
normalizeVNodeSlots(instance, children)
}
}
def(instance.slots, InternalObjectKey, 1)
}
initSlots方法做了什么?
功能: 初始化slots
这一步注释在: initProps和initSlots
applyOptions方法 路径: core\packages\runtime-core\src\componentOptions.ts
export function applyOptions(instance: ComponentInternalInstance) {
const options = resolveMergedOptions(instance)
const publicThis = instance.proxy! as any
const ctx = instance.ctx
shouldCacheAccess = false
if (options.beforeCreate) {
callHook(options.beforeCreate, instance, LifecycleHooks.BEFORE_CREATE)
}
const {
data: dataOptions,
computed: computedOptions,
methods,
watch: watchOptions,
provide: provideOptions,
inject: injectOptions,
created,
beforeMount,
mounted,
beforeUpdate,
updated,
activated,
deactivated,
beforeDestroy,
beforeUnmount,
destroyed,
unmounted,
render,
renderTracked,
renderTriggered,
errorCaptured,
serverPrefetch,
// public API
expose,
inheritAttrs,
// assets
components,
directives,
filters
} = options
if (injectOptions) {}
if (methods) {}
if (dataOptions) {}
shouldCacheAccess = true
if (computedOptions) {}
if (watchOptions) {}
if (provideOptions) {}
if (created) {
callHook(created, instance, LifecycleHooks.CREATED)
}
function registerLifecycleHook(
register: Function,
hook?: Function | Function[]
) {
if (isArray(hook)) {
hook.forEach(_hook => register(_hook.bind(publicThis)))
} else if (hook) {
register((hook as Function).bind(publicThis))
}
}
registerLifecycleHook(onBeforeMount, beforeMount)
registerLifecycleHook(onMounted, mounted)
registerLifecycleHook(onBeforeUpdate, beforeUpdate)
registerLifecycleHook(onUpdated, updated)
registerLifecycleHook(onActivated, activated)
registerLifecycleHook(onDeactivated, deactivated)
registerLifecycleHook(onErrorCaptured, errorCaptured)
registerLifecycleHook(onRenderTracked, renderTracked)
registerLifecycleHook(onRenderTriggered, renderTriggered)
registerLifecycleHook(onBeforeUnmount, beforeUnmount)
registerLifecycleHook(onUnmounted, unmounted)
registerLifecycleHook(onServerPrefetch, serverPrefetch)
if (isArray(expose)) {}
if (render && instance.render === NOOP) {}
if (inheritAttrs != null) {}
if (components) instance.components = components as any
if (directives) instance.directives = directives
}
applyOptions方法做了什么?
功能: 这是对Vue2.0写法进行兼容处理
只要知道对Vue2的写法兼容是在这个applyOptions方法里完成的就行了
这次的注释在applyOptions
解决了这几个todo之后,现在来看剩下的todo,如图
可以看到,现在的todo都指向了一个模块: reactivity(响应式模块)
是的,这也是我们接下来的目标,响应式
到此,Vue3组件初始化流程完结,敬请期待下一期的Vue3响应式模块