- 发布于
Vue3应用初始化到首次渲染
- Authors

- Name
- 田中原
Vue3应用初始化到首次渲染
目录
应用程序初始化
packages/runtime-dom/src/index.ts 的createApp 方法
主要做三件事
- 创建app对象:延迟创建渲染器对象
ensureRenderer - 重写mount方法:
- 重写mount方法,因为createApp是
runtime-dom中针对浏览器平台实现的。而runtime-core/src/apiCreateApp.ts文件中createApp方法中的app.mount是支持跨平台 - 兼容Vuejs2.x写法
- 重写mount方法,因为createApp是
- 调用
mount挂载

创建app对象
延迟创建渲染器对象 ensureRenderer
延迟创建渲染器对象,这样可以使核心渲染器逻辑在用户只从Vue中导入响应式工具时可以被tree-shaking。

渲染器具体实现 baseCreateRender
通过packages/runtime-core/src/renderer.ts的 createRenderer 调用

render函数,以及渲染用的一系列方法
主要创建了渲染操作相关的一系列的函数,最后返回render函数,作为渲染时调用
| 函数名 | 功能描述 |
|---|---|
| patch | 根据不同的 vnode 类型执行不同的逻辑 |
| processText | 处理文本节点 |
| processCommentNode | 处理注释节点 |
| mountStaticNode | 挂载静态节点 |
| patchStaticNode | 更新静态节点 |
| moveStaticNode | 移动静态节点 |
| removeStaticNode | 移除静态节点 |
| processElement | 挂载元素。只针对组件类型的 vnode |
| mountElement | 挂载元素。只针对组件类型的 vnode |
| setScopeId | 设置 scopeId |
| patchElement | 更新元素。只针对组件类型的 vnode |
| patchProps | 更新 props |
| processFragment | 挂载片段 |
| mountChildren | 挂载子节点,深度优先递归调用 path |
| patchChildren | 更新子节点 |
| patchBlockChildren | 更新块子节点 |
| move | 移动节点 |
| next | 获取下一个节点 |
| unmount | 卸载节点 |
| remove | 移除节点 |
| unmountChildren | 卸载子节点 |
| processTextOrComment | 处理文本或注释节点 |
| setupRenderEffect | 设置渲染 effect |
| queuePostRenderEffect | 队列渲染 effect |
创建app对象,从app层面添加全局方法createAppAPI
packages/runtime-core/src/apiCreateApp.ts的createAppAPI
- 创建app对象
- 为app对象添加
use、mixin、component、directive、mount、unmount、provide、runWithContext方法 - 返回app对象
createApp 创建时会将app组件对象作为根组件传入

📌app创建过程通过闭包和函数柯理化实现了参数保留 如:执行app.mount,不需要传入render,因为在createAppApi时渲染器render参数已保留
初始化为什么要重写app.mount
- 兼容Vuejs2.x写法
- 使用API时更灵活
runtime-dom/src/index.ts文件中createApp中重写app.mount

runtime-core/src/apiCreateApp.ts文件中createApp方法中的app.mount 是支持跨平台:
- 先创建vnode再渲染vnode
- 参数rootContainer可根据不同渲染平台不同


渲染核心流程
创建vnode和渲染vnode。
渲染逻辑入口
packages/runtime-core/src/renderer.ts 文件baseCreateRenderer 中定义的render 函数

patch具体实现
packages/runtime-core/src/renderer.ts 文件baseCreateRenderer 中定义的patch 函数。
调用baseCreateRenderer 中各种的方法,主要实现vnode到dom的挂载
- 判断是否第一次挂载,是否有变动。(
n1==null)时表示首次挂载 - 根据vnode节点类型调用不同的处理逻辑: 文本节点、注释节点、静态节点、Fragment、元素、组件、teleport、suspense、无效vnode类型
- 节点处理完成后根据需要设置ref

组件处理processComponent
通过节点类型调用processComponent,判断是挂载还是更新或者是keepLive组件activate。

组件挂载mountComponent
如果是首次挂载调用packages/runtime-core/src/renderer.ts 文件baseCreateRenderer 中定义的mountComponent 函数
组件vnode会比元素vnod多组件的配置componentOptions 和componentInstance 组件的实例
挂载组件:
- 创建组件实例,通过对象的方式创建当前渲染的组件的实例。
- 判断是不是
keepAlive组件,是的话注入renderer - 设置组件实例,保留组件相关数据,维护组件上下文,对props、插槽、以及其他实例的属性的初始化处理
- 设置并运行带副作用的渲染函数
setupRenderEffect
元素挂载mountElement
packages/runtime-core/src/renderer.ts 的processElement 判断完n1 == null 是首次渲染时调用mountElement
mountElement 的主要处理逻辑:
- 根据不同平台创建元素、处理其他类型节点和递归处理子节点
- 调用
created生命周期 - 设置
scopeId、处理props、调用vnodeHook - 调用
beforeMount生命周期 - 插入到
dom - 调用
mounted生命周期