news 2026/2/8 0:26:27

Vue3 应用实例创建及页面渲染底层原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue3 应用实例创建及页面渲染底层原理

整体流程

完整的创建与渲染流程可以分成这些阶段:

  1. 创建 App 实例
  2. 创建根组件实例
  3. 设置响应式状态
  4. 创建渲染器(Renderer)
  5. 挂载 Mount
  6. vnode -> DOM 渲染
  7. 数据变更触发更新
  8. 重新渲染 / diff / patch

流程图大致如下:

createApp() ───> app.mount('#app') │ │ ▼ ▼ createRootComponent createRenderer │ │ ▼ ▼ setup() / render() render(vnode) -> patch │ │ ▼ ▼ effect(fn) ────> scheduler -> patch updates

1、createApp 初始化

Vue 应用的入口通常是:

createApp(App).mount('#app')

从源码看 createApp:

// packages/runtime-core/src/apiCreateApp.ts export function createAppAPI(render) { return function createApp(rootComponent, rootProps = null) { const app = { _component: rootComponent, _props: rootProps, _container: null, _context: createAppContext() } const proxy = (app._instance = { app }) // register global APIs // ... return { mount(container) { const vnode = createVNode(rootComponent, rootProps) app._container = container render(vnode, container) }, unmount() { /* ... */ } } } }

关键点:

  • createAppAPI(render)生成 createApp 函数
  • app 内保存_component、上下文_context
  • app.mount调用render(vnode, container)

render平台渲染器注入(在 web 下是 DOM 渲染器)。

2、createVNode 创建虚拟节点(VNode)

在 mount 前会创建一个虚拟节点:

function createVNode(type, props, children) { const vnode = { type, props, children, shapeFlag: getShapeFlag(type), el: null, key: props && props.key } return vnode }

vnode是渲染的基础单元:

shapeFlag用来快速判断 vnode 类型,是内部性能优化。

3、渲染器 Renderer 初始化

Vue3 是平台无关的(runtime-core),真正依赖 DOM 的是在runtime-dom中。

创建 Renderer:

export const renderer = createRenderer({ createElement: hostCreateElement, patchProp: hostPatchProp, insert: hostInsert, remove: hostRemove, setElementText: hostSetElementText })

createRenderer返回了我们前面在 createApp 中使用的render(vnode, container)函数。

4、render & patch

核心渲染入口:

function render(vnode, container) { patch(null, vnode, container, null, null) }

patch 是渲染补丁函数:

function patch(n1, n2, container, parentComponent, anchor) { const { type, shapeFlag } = n2 if (shapeFlag & ShapeFlags.ELEMENT) { processElement() } else if (shapeFlag & ShapeFlags.STATEFUL_COMPONENT) { processComponent(...) } }

简化为:

  • 如果是DOM 元素 vnode→ 挂载/更新
  • 如果是组件 vnode→ 创建组件实例、挂载、渲染子树

5、组件实例创建

当渲染组件时:

function processComponent(n1, n2, container, parentComponent, anchor) { mountComponent(n2, container, parentComponent, anchor) } function mountComponent(vnode, container, parentComponent, anchor) { const instance = createComponentInstance(vnode, parentComponent) setupComponent(instance) setupRenderEffect(instance, container, anchor) }
  • processComponent 处理组件
  • mountComponent 挂载组件
    • createComponentInstance 创建组件实例
    • setupComponent 创建组件对象

createComponentInstance:

function createComponentInstance(vnode, parent) { const instance = { vnode, parent, proxy: null, ctx: {}, props: {}, attrs: {}, slots: {}, setupState: {}, isMounted: false, subTree: null } return instance }

实例保存基础信息,还没运行 setup。

6、 setupComponent(初始化组件)

function setupComponent(instance) { initProps(instance, vnode.props) initSlots(instance, vnode.children) setupStatefulComponent(instance) }

内部会执行:

const { setup } = Component if (setup) { const setupResult = setup(props, ctx) handleSetupResult(instance, setupResult) }

setup 返回值​:

  • 返回对象 → 作为响应式状态 state
  • 返回函数 → render 函数

最终让组件拥有instance.render

7、创建响应式状态

Vue3 的响应式来自reactivity包:

const state = reactive({ count: 0 })

底层是Proxy拦截 getter/setter:

  • getter:收集依赖
  • setter:触发依赖更新

依赖管理核心是 ​effect / track / trigger​。

8、 setupRenderEffect 与首次渲染

创建渲染器副作用,并调度组件挂载和异步更新:

function setupRenderEffect(instance, container, anchor) { instance.update = effect(function componentEffect() { if (!instance.isMounted) { const subTree = (instance.subTree = instance.render.call(proxy)) patch(null, subTree, container, instance, anchor) instance.isMounted = true } else { // 更新更新逻辑 } }, { scheduler: queueJob }) }

这里:

  • 创建一个响应式 effect
  • 第一次执行 render 得到 subTree
  • patch 子树到 DOM

effect+scheduler实现异步更新。

9、vnode-> 真实 DOM(DOM mount)

当 patch 到真正的 DOM 时,走的是 element 分支:

function processElement(...) { if (!n1) { mountElement(vnode, container) } else { patchElement(n1, n2) } }

mountElement

function mountElement(vnode, container) { const el = (vnode.el = hostCreateElement(vnode.type)) // props for (key in props) { hostPatchProp(el, key, null, props[key]) } // children if (typeof children === 'string') { hostSetElementText(el, children) } else { children.forEach(c => patch(null, c, el)) } hostInsert(el, container) }

10、更新 & Diff 算法

当响应式状态改变:

state.count++

触发 setter →trigger

  • 将 effect 放入更新队列
  • 异步执行 scheduler
  • 调用 instance.update 再次 patch

更新阶段:

patchElement(n1, n2)

核心逻辑:

  1. props diff
  2. children diff
  3. unkeyed/keyed diff算法(最小化移动)

具体见patchChildrenpatchKeyedChildren

整体核心对象关系架构

App └─ vnode(root) └─ ComponentInstance ├─ props / slots ├─ setupState └─ render() -> subTree └─ vnode tree └─ DOM nodes

响应式依赖结构:

reactive state ├─ effects[] └─ track -> effect └─ scheduler -> patch
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/7 4:20:11

计算机毕设java网络相册管理系统 基于Java的在线相册管理系统设计与实现 Java网络相册管理系统的开发与应用

计算机毕设java网络相册管理系统090o29 (配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。随着互联网的飞速发展,人们的生活方式发生了翻天覆地的变化。尤其在疫情期间&…

作者头像 李华
网站建设 2026/2/7 11:12:27

大型语言模型在自动问答系统中的应用

大型语言模型在自动问答系统中的应用 关键词:大型语言模型、自动问答系统、自然语言处理、知识表示、语义理解 摘要:本文深入探讨了大型语言模型在自动问答系统中的应用。首先介绍了相关背景,包括目的范围、预期读者等。接着阐述了核心概念与联系,分析了核心算法原理及具体…

作者头像 李华
网站建设 2026/2/7 22:15:40

花授粉优化算法改进及应用毕业论文【附代码】

✅ 博主简介:擅长数据搜集与处理、建模仿真、程序设计、仿真代码、论文写作与指导,毕业论文、期刊论文经验交流。✅ 具体问题可以私信或扫描文章底部二维码。(1)融合被囊群与差分变异的混合搜索策略 针对基础花授粉算法在处理高维…

作者头像 李华
网站建设 2026/2/7 16:05:59

改进哈里斯鹰与机器学习滑坡预测毕业论文【附代码】

✅ 博主简介:擅长数据搜集与处理、建模仿真、程序设计、仿真代码、论文写作与指导,毕业论文、期刊论文经验交流。✅ 具体问题可以私信或扫描文章底部二维码。(1)基于改进哈里斯鹰优化与遗传规划的IHHO-IBP组合模型 针对传统BP神经…

作者头像 李华
网站建设 2026/2/5 14:01:09

深度学习相干光通信优化算法毕业论文【附代码】

✅ 博主简介:擅长数据搜集与处理、建模仿真、程序设计、仿真代码、论文写作与指导,毕业论文、期刊论文经验交流。 ✅ 具体问题可以私信或扫描文章底部二维码。 (1)低复杂度混合时频域色散均衡方案(Hybrid LDBP&#xf…

作者头像 李华