本页介绍了 Vue.js 2.7 中 <script setup> 功能的编译过程。<script setup> 语法是一种编译时语法糖,它简化了在单文件组件(SFC)中使用组合式 API。它最初在 Vue 3 中引入,并作为 Vue 3 兼容层的一部分,向后移植到 Vue 2.7。有关组合式 API 本身的信息,请参见Vue 3 兼容层和组合式 API。
<script setup> 编译将 <script setup> 块内部编写的代码转换为 Vue 运行时可以理解的标准 Vue 组件选项对象。编译过程在工具链(通过 Webpack、Vite 等)的构建时发生,在使用组合式 API 时提供了更符合人体工程学的开发体验。
来源:packages/compiler-sfc/src/compileScript.ts98-101
<script setup> 编译发生在 compileScript 函数中,该函数接收一个 SFC 描述符(包含组件的各种块)并输出一个经过适当转换的已处理脚本块。
<script> 和 <script setup> 块(如果存在)defineProps、defineEmits、defineExpose)setup() 函数的最终组件定义来源:packages/compiler-sfc/src/compileScript.ts98-1015
当组件同时包含常规的 <script> 块和 <script setup> 块时,编译器会处理并将它们合并。常规的 <script> 包含组件选项,如 name、components 和其他选项。<script setup> 块的内容则被转换为组件的 setup() 函数。
来源:packages/compiler-sfc/src/compileScript.ts627-762
<script setup> 语法引入了几个在编译过程中处理的编译器宏
defineProps 用于声明组件接收的 prop。它可以与运行时对象/数组声明或 TypeScript 类型标注一起使用。
来源:packages/compiler-sfc/src/compileScript.ts301-343
与 defineProps 类似,defineEmits 用于声明事件。它也可以与运行时声明或 TypeScript 一起使用。
来源:packages/compiler-sfc/src/compileScript.ts383-424
defineExpose 定义了哪些属性通过模板引用暴露给父组件。在编译过程中,它被转换为调用 setup 上下文中提供的 expose 函数。
来源:packages/compiler-sfc/src/compileScript.ts466-475
编译过程的一个重要方面是绑定分析。编译器会分析 <script setup> 块中的所有顶级声明,并使它们在模板中可用。
来源:packages/compiler-sfc/src/compileScript.ts1052-1101
编译后,<script setup> 代码会变成一个带有 setup 函数的标准 Vue 组件。当实例被创建时,Vue 运行时会像处理其他组件一样处理该组件。
当一个带有 setup 函数的组件被创建时,Vue 的运行时会遵循以下步骤
| 步骤 | 描述 |
|---|---|
| 初始化组件 | 组件选项被合并并创建组件 |
| 调用 setup 函数 | setup(props, context) 被调用,传入 props 和 setup 上下文 |
| 处理 setup 结果 | 处理 setup 的返回值 |
| 代理 setup 状态 | setup 状态被代理以进行 ref 展开 |
| 渲染组件 | 组件使用 setup 状态进行渲染 |
来源:src/v3/apiSetup.ts28-84, src/core/instance/state.ts51-57
以下是 <script setup> 组件如何被编译器转换的示例
来源:packages/compiler-sfc/test/compileScript.spec.ts56-84, packages/compiler-sfc/test/compileScript.spec.ts112-128, packages/compiler-sfc/test/compileScript.spec.ts172-184
<script setup> 功能拥有强大的 TypeScript 支持,包括
对于基于类型的 prop 定义,编译器会从 TypeScript 类型中提取运行时 prop 验证
来源:packages/compiler-sfc/test/compileScript.spec.ts751-823
当 setup 函数在运行时被调用时,它会接收一个“setup 上下文”对象作为其第二个参数。此上下文提供对各种组件功能的访问
| 上下文属性 | 描述 |
|---|---|
attrs | 传递给组件的非 prop 属性 |
slots | 父组件提供的插槽 |
emit | 用于触发事件的函数 |
expose | 通过引用向父组件暴露属性的函数 |
来源:src/v3/apiSetup.ts20-26, src/v3/apiSetup.ts87-123
<script setup> 编译系统与其他 Vue 系统集成
如果组件包含 CSS 变量(<style> 中的 v-bind),编译器会注入一个 useCssVars 调用,以使响应式 CSS 变量生效。
模板表达式根据绑定分析添加适当的作用域标识符前缀,使模板能够访问 Vue 实例属性和 setup 状态。
来源:packages/compiler-sfc/src/prefixIdentifiers.ts19-82
setup 函数利用 Vue 的 EffectScope 系统,自动收集并清理在组件生命周期内创建的响应式副作用。
来源:src/v3/reactivity/effectScope.ts6-106, src/core/instance/state.ts51-57
<script setup> 编译过程在构建时将简洁的组合式 API 代码转换为标准 Vue 组件选项,提供了更符合人体工程学的开发体验,而没有运行时开销。编译器处理导入、宏、绑定分析和代码生成,以生成优化的 Vue 组件。