vue3-组件创建mountComponent

138 阅读2分钟

创建组件实例过程mountComponent,setup启动函数:

const mountComponent = (initialVNode, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {

  // 创建组件实例,创建实例对象,绑上各种属性
  const instance = (initialVNode.component = createComponentInstance(initialVNode, parentComponent, parentSuspense))

  // 设置组件实例,初始化props/插槽、设置有状态的组件实例
  setupComponent(instance)

  // 设置并运行带副作用的渲染函数
  setupRenderEffect(instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized)

}
//设置组件实例--设置有状态的组件实例,
//1,PublicInstanceProxyHandlers函数设置代理,
//其中利用了缓存,缓存访问的属性的类型,0:setupState,1:data,2:props,3:ctx,且按照这个优先级访问属性
//对渲染上下文 instance.ctx 属性的访问和修改,代理到对 setupState、data、props、ctx 中的数据的访问和修改
//2,执行setup函数,
//如果setup有参数,创建setupContext,返回的对象{attrs,slots,emit},并且把[props, {attrs,slots,emit}]传入setup函数中
//3,处理setup的返回结果,如果是个函数,返回给instance.render,如果是个对象,包裹成reactive的对象赋值给setupState
function setupStatefulComponent (instance, isSSR) {
  const Component = instance.type
  // 创建渲染代理的属性访问缓存
  instance.accessCache = {}
  // 创建渲染上下文代理,设置了get和set拦截,get的时候按照优先级去取值,set的时候按照优先级去赋值,props不能赋值
  instance.proxy = new Proxy(instance.ctx, PublicInstanceProxyHandlers)
  // 判断处理 setup 函数
  const { setup } = Component
  if (setup) {
    // 如果 setup 函数带参数,则创建一个 setupContext
    const setupContext = (instance.setupContext =
      setup.length > 1 ? createSetupContext(instance) : null)
    // 执行 setup 函数,获取结果
    const setupResult = callWithErrorHandling(setup, instance, 0 /* SETUP_FUNCTION */, [instance.props, setupContext])
    // 处理 setup 执行结果
    handleSetupResult(instance, setupResult)
  }
  else {
    // 完成组件实例设置,标准化模板或者渲染函数和兼容 Options API
    finishComponentSetup(instance)
  }
}
//设置setup的context
function createSetupContext (instance) {
  return {
    attrs: instance.attrs,
    slots: instance.slots,
    emit: instance.emit
  }
}
//处理setup的返回结果
function handleSetupResult(instance, setupResult) {
  if (isFunction(setupResult)) {
    // setup 返回渲染函数
    instance.render = setupResult
  }
  else if (isObject(setupResult)) {
    // 把 setup 返回结果变成响应式
    instance.setupState = reactive(setupResult)
  }
  finishComponentSetup(instance)
}