是 vue 编译时语法糖,构建阶段由编译器静态分析顶层声明,自动将非私有(非 _/$ 开头)的变量、函数等注入 setup 返回对象,无需手动 return;import 和私有标识符不暴露。

因为 script setup 是 Vue 的编译时语法糖,不是普通 JS 脚本——它在构建阶段就被 Vue 编译器处理,自动把顶层声明的变量、函数、组件等提取并注入到组件的 setup() 函数返回对象中。
变量自动暴露,无需手动 return
在 <script setup></script> 中声明的顶层响应式变量(如用 ref、reactive、computed 创建的),Vue 编译器会识别并“收集”它们,等价于在普通 setup() 函数里显式 return { count, name, onClick }。
例如:
<script setup>
import { ref } from 'vue'
const count = ref(0)
const name = 'Alice'
function handleClick() { count.value++ }
</script>
会被编译成类似这样的标准 setup 写法:
export default {
setup() {
const count = ref(0)
const name = 'Alice'
function handleClick() { count.value++ }
return { count, name, handleClick } // 编译器自动加了这行
}
}
哪些东西会被自动暴露?
- 顶层 变量声明(
const/let/var):只要不是以_或$开头,且不是import/function声明(除非是命名函数且被引用),都会被暴露 -
函数声明:命名函数(
function foo() {})和函数表达式(const bar = () => {})都会被暴露 -
组件、指令、插件导入:通过
defineComponent、defineAsyncComponent或直接import的组件,配合components选项或自动注册机制可用 -
使用
defineProps/defineEmits声明的 props 和 emits 也会被特殊处理,注入到组件实例中
哪些不会被暴露?
- 以
_或$开头的变量(如const _internal = 1或const $api = {})——视为私有,不暴露给模板 - 纯
import语句(如import axios from 'axios')——只用于内部逻辑,不进入组件上下文 - 未被任何暴露项引用的局部变量(如
const temp = 'x';但没在 return 列表或模板中出现)——会被编译器忽略或移除 -
default export不允许出现在script setup中(会报错)
背后的运行机制:编译时静态分析
Vue 的构建工具(Vite / Vue CLI)在解析 <script setup></script> 时,不会直接执行这段代码,而是用 AST(抽象语法树)进行静态分析:
- 扫描顶层声明,过滤出可暴露的标识符
- 识别
defineProps、defineEmits等宏,并生成对应的运行时逻辑(比如 props 类型校验、emits 触发检查) - 将结果拼合成一个标准的
setup()函数,再参与后续的组件创建流程
所以它不是“魔法”,而是编译阶段的代码转换——开发时写得简洁,运行时仍是标准的 Composition API。










