在 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>
更适合需要显式控制或兼容旧代码的场景。
选择时需权衡 开发效率、维护成本 和 团队习惯。