VUE3 defineProps 5分钟讲清楚

definePropsVue 3 组合式 APIscript setup语法糖)中用于声明组件 Props编译时宏(Compiler Macro)。它的核心作用是让组件明确接收来自父组件的输入参数(Props),并自动处理 Prop 的响应式绑定、类型校验与默认值。

一、基础概念

  • 适用场景 :仅在 <script setup>中使用(Vue 3.2+ 支持),无需手动导入(编译器会自动识别)。

  • 本质 :返回一个只读的响应式对象 ,包含父组件传递的所有 Props(修改 Props 会触发警告,需通过 emit反向通信)。

  • 单向数据流:Props 是"父传子"的单向绑定,子组件不能直接修改 Props,需通过事件通知父组件更新。

二、核心用法

defineProps支持三种声明方式,覆盖从简单到复杂的场景:

1. 数组语法(简单类型)

适用于仅需声明 Prop 名称的场景(无类型校验、默认值或验证):

javascript 复制代码
<script setup>
// 声明两个 Prop:title(字符串)、count(数字)
const props = defineProps(['title', 'count'])
</script>

<template>
  <h1>{{ title }}</h1>
  <p>Count: {{ count }}</p>
</template>
2. 对象语法(带配置项)

适用于需要类型校验、默认值、必填性、自定义验证的场景。对象键为 Prop 名,值为配置对象:

javascript 复制代码
<script setup>
const props = defineProps({
  // 基础类型校验(支持 String/Number/Boolean/Array/Object/Date/Function/Symbol)
  title: {
    type: String,       // 类型(可多个,如 [String, Number])
    required: true,     // 是否必填
    default: 'Default Title' // 默认值(仅当 required: false 时有效)
  },
  // 引用类型默认值需用「工厂函数」返回(避免多实例共享同一引用)
  list: {
    type: Array,
    default: () => []   // 工厂函数返回新数组
  },
  // 自定义验证函数(返回 true 表示合法)
  status: {
    validator(value) {
      return ['active', 'inactive'].includes(value)
    }
  }
})
</script>

配置项说明

选项 类型 说明
type 原生构造函数/数组 校验 Prop 类型(如 StringNumber,或多类型 [String, Number]
required Boolean 是否为必填 Prop
default 任意值/工厂函数 默认值(引用类型必须用工厂函数返回,避免共享)
validator Function 自定义验证函数(参数为 Prop 值,返回布尔值)
3. TypeScript 类型注解(推荐)

若项目使用 TypeScript,类型注解 是最简洁且类型安全的方式(替代对象语法的类型校验)。需配合 defineProps泛型参数使用:

TypeScript 复制代码
<script setup lang="ts">
// 声明 Props 类型(? 表示可选)
interface Props {
  title?: string
  count: number
  list?: string[]
}

// 用泛型传入类型
const props = defineProps<Props>()
</script>

添加默认值

若需给 TS 类型的 Prop 设置默认值,需配合 withDefaults辅助函数(Vue 3.2+ 支持):

TypeScript 复制代码
<script setup lang="ts">
interface Props {
  title?: string
  count?: number
  list?: string[]
}

// withDefaults 接收 defineProps 的结果 + 默认值对象
const props = withDefaults(defineProps<Props>(), {
  title: 'Hello Vue',
  count: 0,
  list: () => ['a', 'b'] // 引用类型仍需工厂函数
})
</script>

三、关键特性

1. 响应式访问

defineProps返回的对象是响应式的,可直接在模板或脚本中使用:

javascript 复制代码
<script setup>
const props = defineProps({ msg: String })
console.log(props.msg) // 响应式值(父组件修改时会更新)
</script>

⚠️ 注意不要直接解构 Props (会丢失响应性)!若需解构,需用 toRefstoRef转换:

javascript 复制代码
<script setup>
import { toRefs, toRef } from 'vue'

const props = defineProps({ msg: String, count: Number })

// 正确:保持响应性
const { msg } = toRefs(props) 
const countRef = toRef(props, 'count') 

// 错误:直接解构会失去响应性
// const { msg, count } = props 
</script>
2. 动态 Props

父组件传递的 Prop 若为响应式数据 (如 ref/reactive),子组件通过 defineProps接收后会自动同步更新:

javascript 复制代码
<!-- 父组件 -->
<script setup>
import { ref } from 'vue'
const parentMsg = ref('Hello from Parent')
</script>
<template>
  <Child :msg="parentMsg" />
  <button @click="parentMsg = 'Updated'">Change</button>
</template>

<!-- 子组件 -->
<script setup>
const props = defineProps({ msg: String })
</script>
<template>
  <p>{{ msg }}</p> <!-- 点击按钮后会更新为 "Updated" -->
</template>
3. 透传 Attributes(v-bind="$attrs")

未被 defineProps声明的 Prop 会被归为透传 Attributes (如 classstyle或自定义未声明的 Prop),可通过 $attrs访问或自动绑定到根元素:

javascript 复制代码
<script setup>
defineProps(['title']) // 仅声明 title
</script>
<template>
  <!-- 未声明的 Prop(如 class、data-id)会自动绑定到 div -->
  <div class="box" data-id="123">{{ title }}</div>
</template>

若需手动控制透传,可使用 useAttrs()(组合式 API):

javascript 复制代码
<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs() // 包含所有透传 Attributes
</script>

四、常见误区与最佳实践

  1. 不要在非 <script setup>中使用definePropsscript setup的专属宏,普通 <script>需用 export default { props: {} }(Vue 2 风格)。

  2. 引用类型默认值必须用工厂函数 :如 default: () => ({})而非 default: {}(否则所有组件实例共享同一对象)。

  3. 优先用 TypeScript 类型注解:比对象语法更简洁,且能享受 TS 的类型提示与校验。

  4. 避免直接修改 Props :如需修改,应通过 emit触发父组件的事件(如 @update:count="val => count = val")。

五、与 Vue 2 的区别

Vue 2 中用 export default { props: {} }声明 Props,而 Vue 3 的 defineProps编译时优化(无运行时开销),且更贴合组合式 API 的风格。

总结

defineProps是 Vue 3 组件通信的核心工具之一,通过简洁的语法实现了类型安全响应式绑定灵活的校验配置

惠州大亚湾

相关推荐
计算机毕设VX:Fegn08952 小时前
计算机毕业设计|基于Java + vue水果商城系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot·课程设计
周杰伦_Jay2 小时前
【 Vue前端技术详细解析】目录结构与数据传递
前端·javascript·vue.js
!停3 小时前
深入理解指针(4)
开发语言·javascript·ecmascript
A24207349303 小时前
JavaScript学习
前端·javascript·学习
奋斗吧程序媛3 小时前
动态组件驱动的标签页架构(简单来说:一个页面包含许多Tabs页面,这些Tabs页面渲染逻辑)
前端·javascript·vue.js
Felix_Fly3 小时前
用 Vue3 + naive-cron 开发 Cron 表达式工具:从 0 到 1 实现生成 + 反解析
前端·javascript·vue.js·vue·cron·naive
开发者小天3 小时前
react中useReducer的使用
前端·javascript·react.js
阿蒙Amon3 小时前
JavaScript学习笔记:1.JavaScript简介
javascript·笔记·学习
小虎牙0073 小时前
关于Android Compose架构的思考
android·前端·mvvm