news 2026/6/8 22:33:44

深入理解 Vue.js 中的「运行时」与「编译时」:从模板到虚拟 DOM 的全过程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入理解 Vue.js 中的「运行时」与「编译时」:从模板到虚拟 DOM 的全过程

在 Vue.js 开发中,你是否曾遇到过这样的错误提示:

You are using the runtime-only build of Vue where the template compiler is not available.

或者在构建工具配置中看到vue.runtime.esm-bundler.js这样的文件名?这些提示都指向 Vue 框架中一个核心但常被误解的概念——运行时(Runtime)与编译时(Compile-time)的区别

本文将通过 Vue 3 的实际机制,彻底解析这两个概念,带你走完从<template>到真实 DOM 的完整旅程,帮你避免常见陷阱,提升对框架底层的理解。


一、什么是「编译时」和「运行时」?

1. 编译时(Compile-time)

  • 定义:代码在构建/打包阶段被处理的过程
  • 发生位置:开发者的本地机器(通过 Vite、Webpack 等构建工具)
  • 典型操作
    • 解析.vue文件中的<template>
    • 将模板编译成 JavaScript 的render函数
    • 静态节点提升、缓存优化
    • Tree-shaking(移除未使用的代码)
    • 生成最终可执行的 JS 包
  • 关键特征不发生在浏览器中,用户不可见

2. 运行时(Runtime)

  • 定义:代码在浏览器中实际执行的阶段
  • 发生位置:用户的浏览器环境
  • 典型操作
    • 执行render函数生成虚拟 DOM(VNode)
    • 响应式系统收集依赖、触发更新
    • 虚拟 DOM diff 算法计算新旧树差异
    • 批量更新真实 DOM
  • 依赖内容:Vue 的运行时核心库(如reactivityrenderer等模块)
  • 关键特征直接影响用户体验和性能

💡通俗类比

  • 编译时= 工厂把原材料加工成预制菜(模板 → render 函数)
  • 运行时= 用户在家加热预制菜并食用(render → 真实 DOM)

二、Vue 3 的两种构建版本:为什么有“运行时-only”?

Vue 3 提供了两种主要的构建产物,其核心区别在于是否包含模板编译器

版本是否含编译器体积(gzip)使用场景典型文件名
完整版(Full Build)✅ 是~30KB直接在浏览器写模板(如 CDN 引入)vue.global.js
运行时-only(Runtime-only)❌ 否~10KB现代工程化项目(Vite / Vue CLI)vue.runtime.esm-bundler.js

现代 Vue 项目默认使用运行时-only 版本,因为模板已在构建阶段被预编译。

为什么这样做?

  • 体积更小:省去约 20KB 的编译器代码
  • 性能更高:避免浏览器实时解析模板的开销
  • 安全性更好:杜绝运行时动态编译带来的 XSS 风险(如v-html+ 动态模板)

三、从<template>到真实 DOM:完整流程拆解

我们以一个简单组件为例,看 Vue 如何完成整个生命周期:

<!-- Counter.vue --> <template> <div class="counter"> <h2>{{ title }}</h2> <p>Count: {{ count }}</p> <button @click="increment">+1</button> </div> </template> <script> export default { data() { return { title: '计数器', count: 0 } }, methods: { increment() { this.count++ } } } </script>

第一步:编译时(构建阶段)

  1. Vite / Webpack 读取.vue文件
  2. @vue/compiler-sfc解析<template>
  3. 模板编译器生成render函数(简化示意):
// 编译后生成的 render 函数(实际更复杂)functionrender(_ctx,_cache,$props,$setup,$data,$options){return(_openBlock(),_createBlock("div",{class:"counter"},[_createVNode("h2",null,_toDisplayString(_ctx.title),1/* TEXT */),_createVNode("p",null,"Count: "+_toDisplayString(_ctx.count),1/* TEXT */),_createVNode("button",{onClick:_ctx.increment},"+1",8/* PROPS */,["onClick"])]))}

🔍 注意:_createVNode就是h()函数的内部实现,用于创建虚拟节点(VNode)

  1. 最终打包产物中不再包含原始模板字符串

第二步:运行时(浏览器执行)

  1. 浏览器加载vue.runtime.esm-bundler.js
  2. Vue 创建组件实例,挂载render函数
  3. 首次渲染
    • 调用render()→ 返回 VNode 树
    • 虚拟 DOM 渲染器(renderer)将 VNode 转为真实 DOM
    • 插入到页面指定容器(如#app
  4. 响应式更新(当count++时):
    • 触发count的 setter
    • 通知依赖(即该组件的render函数)
    • 重新执行render生成新 VNode
    • Diff 新旧 VNode,仅更新<p>文本内容
    • 高效更新真实 DOM

🌟关键结论
浏览器中从未见过你的<template>!它早已在构建时变成了高效的 JavaScript 函数。


四、手写render函数:绕过编译时

如果你不需要模板,可以直接在运行时编写render函数:

import{createApp,h}from'vue'createApp({data(){return{msg:'Hello Render!'}},render(){returnh('div',{style:{color:'blue'}},this.msg)}}).mount('#app')

适用场景:

  • 动态生成 UI(如可视化编辑器)
  • 高性能组件(避免模板解析开销)
  • 与 JSX 混合使用(Vue 3 支持 JSX)

⚠️ 注意:即使手写render,仍需依赖 Vue 的运行时核心(响应式、渲染器等)


五、常见误区与最佳实践

❌ 误区1:认为“运行时-only 不能用模板”

真相:只要使用.vue单文件组件,构建工具会自动编译模板,完全兼容运行时-only

❌ 误区2:在运行时动态拼接模板字符串

// 危险且无效(运行时-only 下会报错)createApp({template:`<div>${dynamicContent}</div>`// ❌})

正确做法:用render函数或v-html(注意 XSS 防护)

✅ 最佳实践:

  1. 工程化项目一律使用运行时-only
  2. 模板用于 90% 的常规组件
  3. 复杂动态逻辑用render函数或 JSX
  4. 不要手动引入完整版 Vue(除非特殊需求)

六、总结:一张图看懂全流程

[开发者写的 .vue 文件] ↓ (编译时:Vite/Webpack + vue/compiler-sfc) [生成 render 函数 + JS 模块] ↓ (打包成 bundle.js) [浏览器加载 vue.runtime + bundle.js] ↓ (运行时:Vue 响应式 + 渲染器) [执行 render → VNode → 真实 DOM]

🔑核心思想
Vue 3 将“编译”与“运行”彻底分离,实现“构建时优化,运行时轻量”
这正是其性能优于许多竞品的关键设计。


结语

理解「运行时」与「编译时」,不仅是解决报错的关键,更是深入掌握 Vue 框架设计哲学的入口。当你下次再看到runtime-only字样时,你会明白:这不仅是一个技术选项,更是 Vue 对性能、安全与工程化的坚定选择。

记住
你写的不是模板,而是未来被执行的函数。
你部署的不是 HTML,而是经过精心编译的高效指令。

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

DeepSeek-R1-0528:8B模型数学推理新突破

深度求索&#xff08;DeepSeek&#xff09;发布的DeepSeek-R1-0528-Qwen3-8B模型在数学推理领域实现重大突破&#xff0c;以8B参数量达到开源模型顶级水平&#xff0c;AIME 2024测试准确率达86.0%&#xff0c;超越Qwen3-235B等大模型表现。 【免费下载链接】DeepSeek-R1-0528-Q…

作者头像 李华
网站建设 2026/5/30 3:56:48

git gc垃圾回收前Fun-ASR语音提醒备份

git gc垃圾回收前Fun-ASR语音提醒备份 在本地AI开发环境中&#xff0c;一次看似普通的 git gc 操作&#xff0c;可能悄然抹去数周的语音识别历史记录。这不是危言耸听——当开发者专注于清理仓库冗余时&#xff0c;很少会意识到&#xff0c;那些未被Git追踪但至关重要的运行时数…

作者头像 李华
网站建设 2026/6/6 6:18:16

Qwen3-14B-FP8:让AI智能切换思维模式的秘诀

Qwen3-14B-FP8&#xff1a;让AI智能切换思维模式的秘诀 【免费下载链接】Qwen3-14B-FP8 项目地址: https://ai.gitcode.com/hf_mirrors/Qwen/Qwen3-14B-FP8 导语 Qwen3-14B-FP8作为Qwen系列最新一代大语言模型&#xff0c;首次实现单模型内无缝切换"思考模式&quo…

作者头像 李华
网站建设 2026/5/28 16:29:09

Happy Island Designer终极指南:10分钟快速掌握岛屿设计技巧

Happy Island Designer终极指南&#xff1a;10分钟快速掌握岛屿设计技巧 【免费下载链接】HappyIslandDesigner "Happy Island Designer (Alpha)"&#xff0c;是一个在线工具&#xff0c;它允许用户设计和定制自己的岛屿。这个工具是受游戏《动物森友会》(Animal Cro…

作者头像 李华
网站建设 2026/5/30 5:24:30

音乐API全能解析:四大平台资源一站式整合方案

音乐API全能解析&#xff1a;四大平台资源一站式整合方案 【免费下载链接】music-api 各大音乐平台的歌曲播放地址获取接口&#xff0c;包含网易云音乐&#xff0c;qq音乐&#xff0c;酷狗音乐等平台 项目地址: https://gitcode.com/gh_mirrors/mu/music-api 还在为音乐…

作者头像 李华
网站建设 2026/6/6 5:07:10

喜马拉雅音频下载器:VIP与付费内容本地化解决方案

喜马拉雅音频下载器&#xff1a;VIP与付费内容本地化解决方案 【免费下载链接】xmly-downloader-qt5 喜马拉雅FM专辑下载器. 支持VIP与付费专辑. 使用GoQt5编写(Not Qt Binding). 项目地址: https://gitcode.com/gh_mirrors/xm/xmly-downloader-qt5 还在为无法离线收听喜…

作者头像 李华