Vue3的
<script setup>语法相比传统Options API写法更加简洁高效。它通过编译宏如
defineProps、defineEmits等替代了defineComponent,减少了样板代码,同时提供更好的TypeScript支持。在
<script setup>中,响应式数据、方法、生命周期等都可以直接编写,代码组织更接近Composition API逻辑。虽然仍支持与Options API混用,但推荐使用纯
<script setup>写法,这是Vue3推荐的开发方式,能自动编译为组件选项,使开发更加高效简洁。
在<script setup>中不需要使用defineComponent
传统写法 vs<script setup>
1.传统 Options API 写法
<!-- 需要 defineComponent --> <script lang="ts"> import { defineComponent } from 'vue'; export default defineComponent({ name: 'MyComponent', props: { title: String }, data() { return { count: 0 }; }, methods: { increment() { this.count++; } } }); </script>2.使用<script setup>(推荐)
<!-- 不需要 defineComponent --> <script setup lang="ts"> import { ref } from 'vue'; // Props 定义 const props = defineProps<{ title: string; }>(); // 响应式数据 const count = ref(0); // 方法 const increment = () => { count.value++; }; </script><script setup>中的替代 API
1.定义 Props
<script setup lang="ts"> // 方式1:使用泛型(推荐) defineProps<{ title: string; count?: number; items: string[]; }>(); // 方式2:使用运行时声明 defineProps({ title: String, count: { type: Number, default: 0 } }); // 方式3:混合使用(Vue 3.3+) interface Props { title: string; count?: number; } defineProps<Props>(); </script>2.定义 Emits
<script setup lang="ts"> // 方式1:使用泛型 const emit = defineEmits<{ (e: 'update', value: string): void; (e: 'submit', payload: { id: number }): void; }>(); // 方式2:数组形式 const emit = defineEmits(['update', 'submit']); // 方式3:对象形式(带验证) const emit = defineEmits({ update: (value: string) => typeof value === 'string', submit: (payload: { id: number }) => payload.id > 0 }); </script>3.定义 Slots 和 Attrs
<script setup lang="ts"> import { useSlots, useAttrs } from 'vue'; const slots = useSlots(); const attrs = useAttrs(); </script>4.定义 Expose
<script setup lang="ts"> import { ref } from 'vue'; const inputRef = ref<HTMLInputElement>(); // 暴露给父组件的方法 defineExpose({ focus: () => inputRef.value?.focus(), clear: () => { if (inputRef.value) inputRef.value.value = ''; } }); </script>为什么不需要defineComponent?
<script setup>的优势:
自动编译:
<script setup>会在编译时转换为正常的组件选项更简洁:减少样板代码
更好的类型推断:TypeScript 支持更好
更直观:代码组织更接近 Composition API 的逻辑
编译对比:
// <script setup> 代码 <script setup lang="ts"> const count = ref(0); </script> // 编译后的结果 ≈ <script lang="ts"> import { defineComponent, ref } from 'vue'; export default defineComponent({ setup() { const count = ref(0); return { count }; } }); </script>特殊情况处理
1.如果需要组件名(用于调试或递归组件)
<!-- 方式1:使用两个 script 标签 --> <script lang="ts"> export default { name: 'MyComponent' }; </script> <script setup lang="ts"> // Composition API 代码 const count = ref(0); </script> <!-- 方式2:使用插件(Vue 3.3+) --> <script setup lang="ts"> defineOptions({ name: 'MyComponent', inheritAttrs: false }); </script>2.混合使用 Options API
虽然不推荐,但如果需要:
<script setup lang="ts"> // Composition API 部分 const count = ref(0); </script> <script lang="ts"> import { defineComponent } from 'vue'; // Options API 部分 export default defineComponent({ name: 'MyComponent', // 这里可以添加 computed, watch 等 computed: { doubled() { // 注意:无法直接访问 setup 中的变量 return 0; } } }); </script>完整示例
<template> <div> <h1>{{ title }}</h1> <p>计数: {{ count }}</p> <button @click="increment">增加</button> <button @click="handleSubmit">提交</button> </div> </template> <script setup lang="ts"> import { ref, onMounted } from 'vue'; // Props interface Props { title: string; initialCount?: number; } const props = withDefaults(defineProps<Props>(), { initialCount: 0 }); // Emits const emit = defineEmits<{ (e: 'update:count', value: number): void; (e: 'submit', payload: { count: number }): void; }>(); // 状态 const count = ref(props.initialCount); // 方法 const increment = () => { count.value++; emit('update:count', count.value); }; const handleSubmit = () => { emit('submit', { count: count.value }); }; // 生命周期 onMounted(() => { console.log('组件已挂载'); }); // 暴露给父组件 defineExpose({ reset: () => { count.value = 0; } }); </script> <style scoped> /* 样式 */ </style>总结
在<script setup>中:
✅不需要
defineComponent✅ 使用
defineProps、defineEmits、defineExpose等编译宏✅ 代码更简洁,类型支持更好
✅ 是 Vue 3 的推荐写法
只有在使用传统 Options API 写法时才需要defineComponent,而<script setup>是 Composition API 的语法糖,会自动处理这些。