在 Vue 3 的 <script setup> 和传统 <script> 写法之间存在几个关键区别,主要体现在代码结构、功能支持和开发体验上。以下是详细对比:
1. 基本语法对比
<script setup>(Composition API 风格)
<script setup lang="ts">
// 直接编写逻辑,自动暴露顶层绑定
import { ref } from 'vue'
const count = ref(0)
</script>
-
特点:
- 顶层变量/函数自动暴露给模板。
- 无需手动注册组件或返回数据。
- 天然支持 TypeScript。
传统 <script>(Options API 或 Composition API)
<script lang="ts">
import { defineComponent, ref } from 'vue'
export default defineComponent({
setup() {
const count = ref(0)
return { count } // 需手动返回
}
})
</script>
-
特点:
- 需要
defineComponent包裹。 - Composition API 需在
setup()函数内编写逻辑并显式返回。 - Options API 需按
data、methods等选项组织代码。
- 需要
2. 核心区别
| 特性 | <script setup> |
传统 <script> |
|---|---|---|
| 代码简洁性 | 更简洁,减少模板代码 | 需要更多样板代码(如 export default) |
| 数据暴露 | 顶层绑定自动暴露 | 需手动返回(Composition API)或定义(Options API) |
| TypeScript 支持 | 原生友好,类型推断更完善 | 需额外类型声明(如 defineComponent) |
| 组件注册 | 直接导入即用 | 需在 components 选项中注册 |
| 指令与宏 | 支持 defineProps、defineEmits 等编译宏 |
需通过 props 和 emits 选项定义 |
| Ref 模板引用 | 直接使用 ref 变量 |
需通过 this.$refs 访问 |
| 生命周期钩子 | 直接导入使用(如 onMounted) |
在 setup() 内或选项式 API 中定义 |
3. 功能差异详解
(1)Props & Emits 声明
-
<script setup>:const props = defineProps<{ msg: string }>() const emit = defineEmits<{ (e: 'update'): void }>() -
传统
<script>:export default defineComponent({ props: { msg: String }, emits: ['update'], setup(props, { emit }) { /* ... */ } })
(2)组件注册
-
<script setup>:<script setup> import ChildComp from './Child.vue' // 自动注册 </script> -
传统
<script>:export default defineComponent({ components: { ChildComp }, // 手动注册 setup() { /* ... */ } })
(3)对外暴露方法
-
<script setup>:
使用defineExpose:const publicMethod = () => {} defineExpose({ publicMethod }) -
传统
<script>:
setup()返回的方法自动暴露。
4. 编译差异
-
<script setup>:- 在编译时转换为高效的渲染函数,无运行时性能开销。
- 宏(如
defineProps)会被编译为静态代码。
-
传统
<script>:- Options API 依赖运行时解析,体积略大。
5. 使用场景建议
| 场景 | 推荐写法 | 理由 |
|---|---|---|
| 新项目/Vue 3 | <script setup> |
更简洁、类型安全、性能优化 |
| 维护旧代码 | 传统 <script>
|
兼容 Options API |
| 需要显式控制暴露 | 传统 <script>
|
setup() 返回更灵活 |
| 库开发 | 根据使用者环境选择 | 确保兼容性 |
6. 代码转换示例
Options API → <script setup>
<!-- 传统 -->
<script>
export default {
data() {
return { count: 0 }
},
methods: {
increment() { this.count++ }
}
}
</script>
<!-- <script setup> -->
<script setup>
const count = ref(0)
const increment = () => count.value++
</script>
Composition API → <script setup>
<!-- 传统 -->
<script>
export default {
setup() {
const count = ref(0)
return { count }
}
}
</script>
<!-- <script setup> -->
<script setup>
const count = ref(0) // 自动暴露
</script>
总结
-
<script setup>是 Vue 3 的现代写法,适合追求简洁和 TypeScript 的项目,但需熟悉编译宏。 -
传统
<script>更适合需要显式控制或兼容旧代码的场景。
选择时需权衡 开发效率、维护成本 和 团队习惯。