CodeWalk

Vue3 script setup与defineProps/defineEmits

作者:苦行僧 · 2026-05-30 12:55

解释Vue3 <script setup>语法糖的核心特性,以及defineProps、defineEmits、defineExpose等编译宏的作用原理。<script setup>相比普通setup函数有哪些编译优化?

回答

苦行僧

<script setup>核心特性

<script setup>
import { ref } from 'vue';
const count = ref(0);
const inc = () => count.value++;
</script>
<template>
  <button @click="inc">{{ count }}</button>
</template>

编译宏(Compiler Macros)

defineProps:声明props,类型推断自动推导

const props = defineProps({
  title: String,
  count: { type: Number, default: 0 }
});
// 或纯类型声明
const props = defineProps<{ title: string; count?: number }>();

defineEmits:声明emit事件

const emit = defineEmits<{
  (e: 'update', id: number): void;
  (e: 'delete'): void;
}>();
// 或运行时声明
const emit = defineEmits(['update', 'delete']);

defineExpose:暴露组件内部属性和方法给父组件(通过模板ref)

const api = { validate() { ... }, reset() { ... } };
defineExpose(api);
// 父组件:<Comp ref="compRef" /> -> compRef.value.validate()

withDefaults:为类型声明props提供默认值

const props = withDefaults(defineProps<{ count?: number }>(), {
  count: 0
});

编译优化

  1. 编译时提升:静态模板在编译时提升(无需每次渲染重建)
  2. 静态Propsv-bind:id="'static'"编译为直接属性赋值
  3. PatchFlags:生成细粒度更新标记,运行时更高效的diff
  4. HoistStatic:静态节点提升到渲染函数之外
  5. 无需return:顶层绑定自动暴露给模板(比普通setup省去return)

普通setup vs script setup

方面setup()script setup
语法需return,模板用this.xxx自动暴露,更简洁
TypeScript类型推断弱强类型推断(宏)
组件注册components选项导入直接import在模板使用
性能标准更多编译时优化

注意事项:

  • 不能使用export default(自动生成)
  • 通过useSlots()useAttrs()代替$slots$attrs
  • defineProps/defineEmits无需额外导入,是编译时宏