- 发布于
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 |
createAppAPI
创建app对象,从app层面添加全局方法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
生命周期