Vue3 的 setup 语法糖是通过 <script setup> 标签启用的特性,它是对 Composition API 的进一步封装,旨在简化组件的声明式写法,同时保留 Composition API 的逻辑组织能力。以下是其核心概念和原理分析:
一、<script setup> 是什么?
-
语法糖本质
它是 Vue3 编译器在编译阶段对组件逻辑的语法转换工具。开发者用更简洁的语法编写逻辑,最终会被编译成标准setup()函数的返回形式。 -
主要特性
- 自动暴露顶层变量(无需
return) - 直接使用
await(自动生成异步包装) - 组件/指令自动注册(无需
components选项) - 支持 TypeScript 类型推导(如
defineProps)
- 自动暴露顶层变量(无需
二、语法糖的编译原理
以下是一个代码转换示例,展示 <script setup> 如何被编译为传统写法:
原始代码(语法糖):
<script setup>
import { ref } from 'vue'
import MyComponent from './MyComponent.vue'
const count = ref(0)
const increment = () => count.value++
</script>
编译后代码:
export default {
setup() {
const count = ref(0)
const increment = () => count.value++
// 自动返回所有顶层变量
return {
count,
increment,
MyComponent // 自动注册组件
}
},
components: {
MyComponent // 编译器自动处理组件注册
}
}
三、关键技术实现
-
编译阶段转换
Vue 编译器(如@vue/compiler-sfc)会在构建时:- 提取
<script setup>中的顶层变量 - 自动生成
return语句暴露这些变量 - 将
import的组件转换为components选项
- 提取
-
响应式绑定
ref或reactive变量会被编译器识别,生成对应的 Proxy 响应式代码。 -
宏函数处理
如defineProps、defineEmits是编译时的特殊宏,编译器会将其转换为标准的 props/emits 声明:<script setup> const props = defineProps({ msg: String }) const emit = defineEmits(['submit']) </script>编译为:
export default { props: { msg: String }, emits: ['submit'], setup(props, { emit }) { // ... } }需要注意的是,Vue从3.5版本开始,已经支持
响应式解构Props,也就是当在同一个 script setup 块中的代码访问从 defineProps 解构出的变量时,Vue 的编译器会自动在前面添加props.。const { foo } = defineProps(['foo']) watchEffect(() => { // 在 3.5 之前仅运行一次 // 在 3.5+ 版本中会在 "foo" prop 改变时重新运行 console.log(foo) })编译为:
const props = defineProps(['foo']) watchEffect(() => { // `foo` 由编译器转换为 `props.foo` console.log(props.foo) })
四、优势与适用场景
| 特性 | 传统 setup 函数 | <script setup> |
|---|---|---|
| 代码量 | 需显式 return | 自动暴露顶层变量 |
| 组件注册 | 需在 components 声明 | 自动注册导入的组件 |
| 异步逻辑 | 需手动包装异步上下文 | 直接使用 await |
| TypeScript 支持 | 需类型断言 | 自动推导 props/emit 类型 |
适用场景:适用于需要清晰逻辑组织的复杂组件,尤其是需要 TypeScript 强类型支持或大量 Composition API 复用的场景。
五、@vue/compiler-sfc核心解析
@vue/compiler-sfc是Vue官方的单文件(SFC)编译器,负责将.vue文件解析为标准的JavaScript模块,它的主要任务包括:
- 分离
<template>、<script>、<style>三大块 - 处理模版编译为渲染函数
- 转换
<script setup>语法糖 - 处理 CSS 作用域(Scoped CSS)
关键功能实现
-
模板编译
将 HTML-like 模板转换为 虚拟 DOM 渲染函数:<!-- 输入 --> <template> <div @click="count++">{{ count }}</div> </template>// 输出渲染函数 import { createElementVNode as _createElementVNode } from "vue" export function render(_ctx) { return _createElementVNode("div", { onClick: _ctx.increment }, _toDisplayString(_ctx.count)) } -
<script setup>转换
将顶层变量自动注入setup()返回对象:<script setup> import { ref } from 'vue' const count = ref(0) </script>// 转换后 export default { setup() { const count = ref(0) return { count } // 自动注入 } } -
CSS 作用域处理
为 Scoped CSS 添加唯一哈希属性:<style scoped> .box { color: red; } </style>.box[data-v-5f8d2c] { color: red; }
与其他工具协作
- 与 Vite:通过
@vitejs/plugin-vue插件集成,实现开发时热更新 - 与 Webpack:通过
vue-loader调用@vue/compiler-sfc - 与 TypeScript:通过
defineProps/defineEmits实现类型推导
SFC在线演练场
访问Vue SFC Playground直接输入 Vue SFC 代码,右侧会实时显示编译后的 JavaScript 代码。

六、总结
通过编译时的智能转换,<script setup> 在保持逻辑组织能力的同时,大幅减少了样板代码,是 Vue3 开发的高效实践方案。
以上就是对 setup 语法糖的一点点介绍啦^-^



















