Vue3源码阅读(四)mount

Mount

  • 源码位于packages/runtime-core/src/apiCreateApp.ts
      mount(
        rootContainer: HostElement,
        isHydrate?: boolean,
        isSVG?: boolean
      ): any {
        // 若还未渲染
        if (!isMounted) {
         //调用createVNode获取vnode,rootComponent即为调用createApp(config)的时候传递进来的config数据,rootProps为root props,前面提到过会对此进行校验,一般在使用过程中rootProps为null;
          const vnode = createVNode(
            rootComponent as ConcreteComponent,
            rootProps
          )
          // store app context on the root VNode.
          // this will be set on the root instance on initial mount.
          //存储context到根节点上   
          vnode.appContext = context

          // HMR root reload
          if (__DEV__) {
            context.reload = () => {
              render(cloneVNode(vnode), rootContainer, isSVG)
            }
          }
          // 调用渲染函数,核心渲染代码为render函数
          if (isHydrate && hydrate) {
            hydrate(vnode as VNode<Node, Element>, rootContainer as any)
          } else {
            render(vnode, rootContainer, isSVG)
          }
          // isMounted置为true 
          isMounted = true
          //  实例的_container保存为当前rootContainer;
          app._container = rootContainer
          // for devtools and telemetry
          // rootContainer增加属性__vue_app__,置为当前app实例
          ;(rootContainer as any).__vue_app__ = app
         
          if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
            app._instance = vnode.component
            devtoolsInitApp(app, version)
          }
          // 返回vnode.component的代理 
          return vnode.component!.proxy
        } else if (__DEV__) {
          warn(
            `App has already been mounted.\n` +
              `If you want to remount the same app, move your app creation logic ` +
              `into a factory function and create fresh app instances for each ` +
              `mount - e.g. \`const createMyApp = () => createApp(App)\``
          )
        }
      }

render

  • render函数的作用在Vue2和Vue3中是完全不一样的,
    • Vue2中render函数是做具体工作的,是真正的render操作,返回的结果是vnode
    • Vue3中render函数是做分发工作的,相当于是一个路由器,两条线路,unmount和patch,无返回结果。
  • vue3.x源码位于runtime-core/src/renderer.ts
    const render: RootRenderFunction = (vnode, container, isSVG) => {
    if (vnode == null) {
      if (container._vnode) {
        // 若要更新到页面上的vnode为null,且要展现的容器的_vnode不为空,也就是有之前的DOM渲染,则调用unmount
        unmount(container._vnode, null, null, true)
      }
    } else {
      //若要更新的vnode非空则调用patch,dom diff和渲染  
      patch(container._vnode || null, vnode, container, null, null, null, isSVG)
    }
    // 调用flushPostFlushCbs回调调度器,使用Promise实现
    // 与Vue2的区别是Vue2是宏任务或微任务来处理的
    flushPostFlushCbs()
    container._vnode = vnode
  }
  • 回调调度器flushPostFlushCbs部分
export interface SchedulerJob extends Function {
  id?: number
  active?: boolean
  computed?: boolean
  allowRecurse?: boolean
  ownerInstance?: ComponentInternalInstance
}
const pendingPostFlushCbs: SchedulerJob[] = []
export function flushPostFlushCbs(seen?: CountMap) {
  if (pendingPostFlushCbs.length) {
    const deduped = [...new Set(pendingPostFlushCbs)]
    pendingPostFlushCbs.length = 0

    // #1947 already has active queue, nested flushPostFlushCbs call
    if (activePostFlushCbs) {
      activePostFlushCbs.push(...deduped)
      return
    }

    activePostFlushCbs = deduped
    if (__DEV__) {
      seen = seen || new Map()
    }

    activePostFlushCbs.sort((a, b) => getId(a) - getId(b))

    for (
      postFlushIndex = 0;
      postFlushIndex < activePostFlushCbs.length;
      postFlushIndex++
    ) {
      if (
        __DEV__ &&
        checkRecursiveUpdates(seen!, activePostFlushCbs[postFlushIndex])
      ) {
        continue
      }
      activePostFlushCbs[postFlushIndex]()
    }
    activePostFlushCbs = null
    postFlushIndex = 0
  }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值