- 发布于
 
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生命周期