关于Vue 3 <script setup> defineXXX API 总结

学!

目录

引言

在 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
相关推荐
万少17 小时前
HarmonyOS官方模板集成创新活动-流蓝卡片
前端·harmonyos
-To be number.wan20 小时前
C++ 赋值运算符重载:深拷贝 vs 浅拷贝的生死线!
前端·c++
噢,我明白了20 小时前
JavaScript 中处理时间格式的核心方式
前端·javascript
纸上的彩虹21 小时前
半年一百个页面,重构系统也重构了我对前端工作的理解
前端·程序员·架构
be or not to be21 小时前
深入理解 CSS 浮动布局(float)
前端·css
LYFlied1 天前
【每日算法】LeetCode 1143. 最长公共子序列
前端·算法·leetcode·职场和发展·动态规划
老华带你飞1 天前
农产品销售管理|基于java + vue农产品销售管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
小徐_23331 天前
2025 前端开源三年,npm 发包卡我半天
前端·npm·github
C_心欲无痕1 天前
vue3 - 类与样式的绑定
javascript·vue.js·vue3
GIS之路1 天前
GIS 数据转换:使用 GDAL 将 Shp 转换为 GeoJSON 数据
前端