【ChatGPT带你学Vue】Vue3 核心源码解析(1)createApp 、h函数、nextTick

本文深入解析Vue3的核心源码,包括createApp的实现,如ensureRenderer、baseCreateRenderer、createAppAPI、createAppContext,以及h函数的创建VNode过程和nextTick的异步任务调度。文中详细阐述了createApp的启动过程、renderer的创建、VNode的生成以及异步更新队列的管理,帮助读者理解Vue3内部的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先安利一个非常好用的小站,清晰地梳理了Vue3源码的一些核心模块,结合ChatGPT插件的代码解释功能一起阅读,无比丝滑!下面就记录一下AI帮我分析的源码相关内容。

再次感谢原作者,本篇对应的原文章链接: CreateApp


目录

​​​​​​​createApp

概览

createApp实现

rendererOptions和ensureRenderer实现

createRenderer实现

baseCreateRenderer实现

createAppAPI 实现

createAppContext 实现

h函数

概览

 h函数实现

_createVNode 实现

 

nextTick 

概览

queueJob 和 queuePostFlushCb实现

queueFlush实现

flushJobs实现

关于queueJob及queuePostFlushCb的调用时机 


createApp

概览

createApp函数是Vue的启动函数,用于返回一个Vue应用程序实例。这部分的文章讨论了CreateApp函数的实现细节,并解释了其中的关键部分,如ensureRenderer和baseCreateRenderer。ensureRenderer用于创建渲染器,而baseCreateRenderer用于实现vnode、diff和patch,最终返回一个对象,其中包含处理DOM节点操作和其他相关内容的方法。createApp方法用于创建一个Vue应用程序实例,涉及到了createAppContext、baseCreateRenderer和createAppAPI等方法的实现。

createApp实现

export const createApp = ((...args) => {
  const app = ensureRenderer().createApp(...args)

  if (__DEV__) {
    injectNativeTagCheck(app)
  }

  const { mount } = app
  app.mount = (containerOrSelector: Element | string): any => {
    const container = normalizeContainer(containerOrSelector)
    if (!container) return
    const component = app._component
    if (!isFunction(component) && !component.render && !component.template) {
      component.template = container.innerHTML
    }
    // clear content before mounting
    container.innerHTML = ''
    const proxy = mount(container)
    container.removeAttribute('v-cloak')
    return proxy
  }

  return app
}) as CreateAppFunction<Element>

这段代码定义了一个 createApp 函数,该函数返回一个应用程序实例,该实例包含 mount 方法,用于将应用程序挂载到指定的容器上。

createApp 函数接受任意个数的参数,并使用 ensureRenderer 函数创建一个应用程序实例 app。如果处于开发环境下,会调用 injectNativeTagCheck 函数注入本地标签检查。

在 mount 方法中,首先使用 normalizeContainer 函数将传入的容器参数转换为 Element 类型的容器元素。如果容器不存在,则直接返回。接着判断组件是否为函数式组件或者具有 render 方法或者具有 template 属性,如果不是,则将容器的 innerHTML 赋值给组件的 template 属性。

然后清空容器的内容,并调用 app 实例的 mount 方法将应用程序挂载到容器上。最后移除容器上的 v-cloak 属性,并返回 mount 方法的返回值作为代理。

最后,使用 as 关键字将 createApp 函数转换为 CreateAppFunction<Element> 类型的函数。

rendererOptions和ensureRenderer实现

const rendererOptions = {
  patchProp,  // 处理 props 属性 
  ...nodeOps // 处理 DOM 节点操作
}

// lazy create the renderer - this makes core renderer logic tree-shakable
// in case the user only imports reactivity utilities from Vue.
let renderer: Renderer | HydrationRenderer

let enabledHydration = false

function ensureRenderer() {
  return renderer || (renderer = createRenderer(rendererOptions))
}

这段代码定义了一个 rendererOptions 对象,该对象包含了 patchProp 属性和 nodeOps 对象。其中 patchProp 属性用于处理组件的 props 属性,nodeOps 对象用于处理 DOM 节点操作。

接着定义了一个 renderer 变量和一个 enabledHydration 变量。renderer 变量用于存储渲染器实例,如果渲染器实例不存在,则通过 createRenderer 函数创建一个渲染器实例。enabledHydration 变量用于存储是否启用了服务端渲染的标志。

最后定义了 ensureRenderer 函数,该函数用于确保渲染器实例存在。如果渲染器实例已经存在,则直接返回该实例。否则,使用 createRenderer 函数创建一个渲染器实例,并将该实例赋值给 renderer 变量,然后返回该实例。这样做可以使得核心渲染器逻辑具有可tree-shaking的特性,以便用户只导入 Vue 的响应式工具时可以减小打包体积。

createRenderer实现

export function createRenderer<
  HostNode = RendererNode,
  HostElement = RendererElement
>(options: RendererOptions<HostNode, HostElement>) {
  return baseCreateRenderer<HostNode, HostElement>(options)
}

这段代码定义了一个 createRenderer 函数,该函数接受一个泛型类型参数 HostNode 和 HostElement,以及一个 RendererOptions 对象作为参数。该函数的返回值是一个渲染器实例。

在函数内部,调用了 baseCreateRenderer 函数,并将传入的 options 参数作为参数传递给 baseCreateRenderer 函数。baseCreateRenderer 函数是 Vue.js 内部的一个函数,它接受一个 RendererOptions 对象作为参数,并返回一个渲染器实例。

createRenderer 函数的作用是封装 baseCreateRenderer 函数,同时通过泛型类型参数 HostNode 和 HostElement,可以实现对不同宿主环境的支持。例如,在浏览器环境下,HostNode 可以是 HTMLElement 类型,HostElement 可以是 Element 类型。而在 Node.js 环境下,HostNode 可以是 Node 类型,HostElement 可以是 DocumentFragment 类型。

baseCreateRenderer实现


                
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Koen_Lee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值