学!
目录
- 引言
- defineProps
- defineEmits
- defineExpose
- [defineSlots(Vue 3.4+)](#defineSlots(Vue 3.4+))
- defineAsyncComponent
- [defineModel(Vue 3.3+)](#defineModel(Vue 3.3+))
- 数据流可视化
引言
在 Vue 3 的 <script setup> 中,有一系列以 define 开头的 API,用于简化组件的 props、事件、插槽、暴露接口等声明。它们是组合式 API 的语法糖,支持 TypeScript 类型推导,并显著减少模板和 JS 的冗余写法。
defineProps
- 声明组件接收的 props。
- 支持 TypeScript 类型推导。
- 取代了传统的 props: {} 配置。
typescript
<script setup lang="ts">
interface Props {
title: string
count?: number
}
const props = defineProps<Props>()
</script>
<template>
<h1>{{ props.title }} - {{ props.count }}</h1>
</template>
可以直接解构:
typescript
const { title, count } = defineProps<{ title: string, count?: number }>()
父组件传入的值,会自动映射到 props 上。
defineEmits
- 声明组件可触发的事件。
- 在 TypeScript 下自动检查事件名称和参数类型。
- 取代了传统的 this.$emit,并提供类型安全。
typescript
<script setup lang="ts">
const emit = defineEmits<{
(e: 'update', value: number): void
(e: 'delete'): void
}>()
function handleClick() {
emit('update', 42)
emit('delete')
}
</script>
emit 对象用于触发事件。
提供类型检查,避免事件名写错或参数类型错误。
defineExpose
- 显式暴露子组件的属性或方法给父组件。
- 父组件通过 ref 获取子组件实例时,只有
defineExpose暴露的内容可访问。 - 用于
<script setup>,是setup(props, { expose })的语法糖。
typescript
<script setup lang="ts">
import { ref } from 'vue'
const count = ref(0)
function increment() { count.value++ }
defineExpose({ count, increment })
</script>
父组件访问方式:
typescript
const childRef = ref(null)
childRef.value.increment()
console.log(childRef.value.count)
defineSlots(Vue 3.4+)
- 声明组件可接收的插槽类型。
- 支持 TypeScript 类型推导。
- 用于
<script setup>下的插槽类型安全。
typescript
<script setup lang="ts">
const slots = defineSlots<{
header?: () => any
footer?: () => any
}>()
</script>
<template>
<header v-if="slots.header">{{ slots.header() }}</header>
<footer v-if="slots.footer">{{ slots.footer() }}</footer>
</template>
defineAsyncComponent
- 定义异步加载组件。
- 按需加载,减少初始包体积。
- 可配置加载组件、失败组件、超时等。
typescript
import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent(() => import('./MyComp.vue'))
可与 <component :is="AsyncComp" /> 配合动态渲染。
defineModel(Vue 3.3+)
- 简化 v-model 双向绑定。
- 支持 TypeScript 类型推导。
- 自动生成 modelValue 和 update:modelValue 的类型绑定。
typescript
<script setup lang="ts">
defineModel('modelValue', Number)
</script>
<template>
<input v-model="modelValue" />
</template>
数据流可视化
typescript
┌───────────── Parent ─────────────┐
│ │
│ props (父传子) │
│ ┌───────────────┐ │
│ │ defineProps │<───父组件传值───┐
│ └───────────────┘ │
│ │
│ emits (子传父) │
│ ┌───────────────┐ │
│ │ defineEmits │ ───触发事件────>│
│ └───────────────┘ │
│ │
│ ref 获取子组件实例 │
│ ┌───────────────┐ │
│ │ defineExpose │───暴露方法/属性─>│
│ └───────────────┘ │
│ │
│ slots (父传子内容) │
│ ┌───────────────┐ │
│ │ defineSlots │<─ 父组件传slot──┐
│ └───────────────┘ │
└─────────────────────────────────┘
- 父 → 子:props(defineProps)、slots(defineSlots)
- 子 → 父:emits(defineEmits)
- 父通过 ref → 子:defineExpose 暴露的内容
- 双向绑定:defineModel