之前文章分析过,createApp 方法执行完后,会赋值给 app,而 app 里 mount 方法是 vue 的挂载方法。
组件渲染、proxy 代理都在这个方法里面。
const { mount } = app//重写 mount 方法app.mount = (containerOrSelector: Element | ShadowRoot | string): any => {//先清空挂载标签下的内容container.innerHTML = \\\'\\\'//执行 mount 方法const proxy = mount(container)//返回 proxyreturn proxy}
mount(rootContainer: HostElement, isHydrate?: boolean): any {if (!isMounted) {const vnode = createVNode(rootComponent as ConcreteComponent,rootProps)//渲染vnode,挂载到页面指定的 demo 上render(vnode, rootContainer)//设置为 trueisMounted = truereturn vnode.component!.proxy}else{//...}}
const render: RootRenderFunction = (vnode, container) => {//执行 patch 方法patch(container._vnode || null, vnode, container)}//通过 patch 方法跳转到 过程组件processComponent(n1,n2,container,anchor,parentComponent,parentSuspense,isSVG,optimized)//通过过程组件,跳转到挂载组件方法mountComponent(n2,container,anchor,parentComponent,parentSuspense,isSVG,optimized)
const mountComponent: MountComponentFn = (initialVNode,container,anchor,parentComponent,parentSuspense,isSVG,optimized) => {//实例化组件const instance: ComponentInternalInstance = (initialVNode.component = createComponentInstance(initialVNode,parentComponent,parentSuspense))//设置组件setupComponent(instance)}
export function createComponentInstance(vnode: VNode,parent: ComponentInternalInstance | null,suspense: SuspenseBoundary | null) {//VNode 类型const type = vnode.type as ConcreteComponent// inherit parent app context - or - if root, adopt from root vnode//继承父组件实例的 appContext ,如果是根组件,则从根 VNode 中取const appContext =(parent ? parent.appContext : vnode.appContext) || emptyAppContext//初始化当前组件实例//实例中添加了很多属性,uid、vnode、数据、是否挂载、是否卸载、生命周期等等...const instance: ComponentInternalInstance = {uid: uid++,vnode,// statectx: EMPTY_OBJ,data: EMPTY_OBJ,props: EMPTY_OBJ,// lifecycle hooksisMounted: false,bc: null,c: null,bm: null,...}//声明是否是根组件instance.root = parent ? parent.root : instance//派发事件instance.emit = emit.bind(null, instance)return instance}
export function setupComponent(instance: ComponentInternalInstance,isSSR = false) {//解构数据和子组件和状态const { props, children, shapeFlag } = instance.vnode//判断是否是有状态的const isStateful = shapeFlag & ShapeFlags.STATEFUL_COMPONENT//初始化 props 和 slotsinitProps(instance, props, isStateful, isSSR)initSlots(instance, children)//根据 isStateful 来创建有状态的组件const setupResult = isStateful? setupStatefulComponent(instance, isSSR): undefinedisInSSRComponentSetup = false// 并返回结果return setupResult}
function setupStatefulComponent(instance: ComponentInternalInstance,isSSR: boolean){//渲染代理的属性访问缓存instance.accessCache = Object.create(null)instance.proxy = new Proxy(instance.ctx, PublicInstanceProxyHandlers)const { setup } = Componentif (setup) {const setupContext = (instance.setupContext =setup.length > 1 ? createSetupContext(instance) : null)currentInstance = instancepauseTracking()resetTracking()currentInstance = null//...//处理 setup 结果handleSetupResult(instance, setupResult, isSSR)} else {//完成组件 设置finishComponentSetup(instance, isSSR)}}
原创文章,作者:小道研究,如若转载,请注明出处:https://www.sudun.com/ask/34629.html