vue3项目里面.vue 文件的执行顺序
不是同时编译:三个部分的编译有先后顺序和依赖关系Template 编译需要 Script 的信息(props、setup 返回值等)Style 编译需要 Template 生成的 scopeId实际执行可能部分并行:现代工具(Vite)会尽可能并行处理,但会处理依赖最终是串行组合:所有部分编译完成后,串行组合成最终模块编译时信息传递:通过唯一的组件 ID 和 AST 分析来传递信息plaintex
Vue3 单文件组件(.vue)的渲染过程是一个「从代码解析到 DOM 挂载」的有序流程,核心围绕「编译阶段」和「运行时阶段」展开
一个 .vue 文件的结构:
<!-- 1. 模板部分 (template) -->
<template>
<div>{{ msg }}</div>
</template>
<!-- 2. 脚本部分 (script setup) -->
<script setup lang="ts">
import { ref, onMounted } from 'vue'
// 响应式数据
const msg = ref('Hello Vue3')
// 生命周期钩子
onMounted(() => {
console.log('组件挂载完成')
})
</script>
<!-- 3. 样式部分 (style) -->
<style scoped>
div { color: red; }
</style>
整体渲染流程(宏观):Vue3 处理 .vue 文件分为两大阶段:
一、编译阶段(构建时,如 Vite/webpack 打包):
构建工具(与浏览器无关)把 .vue 文件解析为 JS 模块(浏览器无法直接识别 .vue,需编译);
构建工具(Vite/webpack + vue-loader)会将 .vue 文件拆分为 3 部分处理:
1、template 编译:
把模板字符串编译为「渲染函数(render)」—— 本质是将 <div>{{ msg }}</div> 转为 _createVNode("div", null, msg.value) 这类 VNode(Virtual Node,虚拟节点) 生成代码
2、script 编译:
- 若用
<script setup>,会被编译为「组件 setup 函数」(自动提升顶层变量 / 导入为响应式上下文) - 若用传统
<script>,会保留export default { setup(), ... }结构
3、style 编译:
- 处理
scoped/module等属性(如添加data-v-xxx作用域标识) - 提取样式,最终注入到 HTML 的
<style>标签(或打包为 CSS 文件)
编译依赖关系链:
script 编译
↓ (提供:props、setup 返回值、组件配置)
template 编译 ←─┐
↓ (提供:scopeId、CSS 映射) │
style 编译 ←─────┘
↓
最终组合

总结
-
不是同时编译:三个部分的编译有先后顺序和依赖关系
-
主要依赖关系:
Template 编译需要 Script 的信息(props、setup 返回值等)
Style 编译需要 Template 生成的 scopeId -
实际执行可能部分并行:现代工具(Vite)会尽可能并行处理,但会处理依赖
-
最终是串行组合:所有部分编译完成后,串行组合成最终模块
-
编译时信息传递:通过唯一的组件 ID 和 AST 分析来传递信息
注:
浏览器原生支持的核心语言:HTML、CASS、JavaScript,其他语言不能直接被浏览器识别,需要先转换为 JavaScript 或 WebAssembly。
浏览器通过 Content-Type 判断如何解析内容:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
<!-- 浏览器:这是 HTML,我要解析为 DOM -->
HTTP/1.1 200 OK
Content-Type: application/javascript
<!-- 浏览器:这是 JS,我要执行它 -->
二、运行时阶段(浏览器执行):
编译后的 .vue 组件被导入并使用(如 import MyComponent from './MyComponent.vue'),编译后的 JS 模块执行,完成组件实例化、渲染、挂载。此时进入运行时执行流程
1:组件实例化准备
Vue 内部创建组件实例,初始化组件上下文(props、slots、attrs 等),为后续执行做准备。(无用户可见输出,Vue 内部完成)
2:执行 <script setup> 代码(setup 函数执行)
执行 <script setup> 内的顶层代码,包括导入、数据声明、钩子注册、同步代码执行。
在 Vue3 的
<script setup>语法中,「setup 顶层代码」指的是<script setup>标签内所有「不在函数 / 钩子内部」的直接执行代码—— 这些代码会在组件实例化时、setup函数执行阶段「最先且仅执行一次」,是组件运行时第一个执行的用户代码。顶层代码中声明的变量、函数、导入的组件,会自动暴露给模板(无需手动return,这是<script setup>的核心语法糖)
<script setup>
import { ref, onBeforeMount, onMounted } from 'vue' // ① 顶层导入
const msg = ref('Hello Vue3') // ② 声明响应式数据
onBeforeMount(() => console.log('挂载前')) // ③ 注册生命周期钩子
onMounted(() => console.log('挂载完成')) // ③ 注册生命周期钩子
console.log('setup 执行,msg:', msg.value) // ④ 执行顶层同步代码
</script>
setup 执行,msg: Hello Vue3
误区 :
把「钩子注册」当成「钩子执行」
<script setup>
// 顶层代码:仅「注册」onMounted 钩子,不会立即执行内部代码
onMounted(() => {
console.log('mounted 执行') // 这行要等 DOM 挂载后才执行
})
// 顶层代码:立即执行
console.log('顶层代码执行')
</script>
3:执行渲染函数(生成 VNode)
- 操作描述:调用编译后的 render 函数,结合 setup 上下文的响应式数据生成 VNode。
- 编译后 render 函数示例(Vue 内部生成):
function render(_ctx, _cache) { return _createVNode("div", null, _ctx.msg) } - 输出示例:(无直接控制台输出,Vue 内部生成 VNode 数据结构)
4:VNode 转换为真实 DOM
- 操作描述:Vue 内部通过 patch 算法将 VNode 转换为真实 DOM 节点(未挂载到页面)。
- 输出示例:(无用户可见输出,Vue 内部完成 DOM 节点创建)
5:触发 beforeMount 钩子
- 操作描述:执行注册的
onBeforeMount钩子函数。 - 输出示例:
挂载前
6:真实 DOM 挂载到页面
- 操作描述:将创建好的真实 DOM 节点插入到指定的挂载容器(如
#app)。 - 输出示例:(页面上可见
<div>Hello Vue3</div>元素,无控制台输出)
7:触发 mounted 钩子
操作描述:执行注册的 onMounted 钩子函数,可操作真实 DOM。
代码示例(钩子内操作 DOM):
onMounted(() => {
const dom = document.querySelector('div')
console.log('挂载完成,DOM 内容:', dom.innerText)
})
输出示例:
挂载完成,DOM 内容: Hello Vue3
8:样式生效
- 操作描述:编译后的 CSS 样式(如 scoped 样式)应用到 DOM 节点。
- 代码示例:
<style scoped> div { color: red; } </style> - 输出示例:(页面上
<div>文字变为红色,无控制台输出)
整体控制台输出顺序总结
plaintext
setup 执行,msg: Hello Vue3
挂载前
挂载完成,DOM 内容: Hello Vue3
页面上则依次完成 DOM 挂载和样式渲染,最终显示红色的「Hello Vue3」文本。
「setup 顶层代码」指的是 <script setup> 标签内所有「不在函数 / 钩子内部」的直接执行代码—— 这些代码会在组件实例化时、setup 函数执行阶段「最先且仅执行一次」,是组件运行时第一个执行的用户代码。
补充:响应式更新时的执行顺序(非首次渲染)
若后续响应式数据变化(如 msg.value = 'New Value'),执行顺序变为:
- 响应式数据触发依赖收集 → 重新执行渲染函数,生成新的 VNode;
- Vue 对比新旧 VNode(diff 算法),计算最小更新量;
- 更新真实 DOM(仅更新变化的部分);
- 触发
onUpdated钩子。
更多推荐


所有评论(0)