非常好 👍
下面我来系统讲解 Vue 3 中 Props 的声明与使用方法,从基础到进阶全面讲透。
内容适合所有使用 Vue 3(Composition API / <script setup>)的开发者。


📘 Vue 3 Props 声明与使用全指南

一、什么是 Props?

Props(属性) 是父组件向子组件传递数据的机制。
父组件传值 → 子组件通过 props 接收并使用。

&lt;!-- 父组件 -->
&lt;Child :title="msg" />

&lt;!-- 子组件 -->
&lt;script setup>
const props = defineProps(['title'])
&lt;/script>

&lt;template>
  &lt;p>{{ title }}&lt;/p>
&lt;/template>


二、Props 的三种声明方式

✅ 1. 简单字符串数组(最基础)

&lt;script setup>
const props = defineProps(['title', 'count'])
&lt;/script>

📌 适合快速开发,不支持类型、默认值、校验。


✅ 2. 对象语法(传统方式)

&lt;script setup>
const props = defineProps({
  title: {
    type: String,
    default: '默认标题'
  },
  count: {
    type: Number,
    required: true
  },
  isActive: Boolean  // 简写形式
})
&lt;/script>

🧩 参数说明:

选项作用示例
type指定类型String, Number, Boolean, Array, Object, Function
required是否必传required: true
default默认值default: 'Hello'
validator自定义验证函数validator: v => ['A', 'B'].includes(v)

✅ 3. 使用 TypeScript 接口定义(推荐现代写法)

&lt;script setup lang="ts">
interface Props {
  title: string
  count?: number
  isActive?: boolean
}

const props = defineProps&lt;Props>()
&lt;/script>

🧠 优点:

  • IDE 自动补全和类型检查;
  • 更简洁;
  • 更适合大型项目。

三、结合默认值:withDefaults

使用类型定义时不能直接设置 default,此时可用 withDefaults()

&lt;script setup lang="ts">
interface Props {
  title?: string
  count?: number
}

const props = withDefaults(defineProps&lt;Props>(), {
  title: '默认标题',
  count: 0
})
&lt;/script>

✅ 相当于:

const props = defineProps({
  title: { type: String, default: '默认标题' },
  count: { type: Number, default: 0 }
})


四、在模板中使用 Props

模板中可以直接访问 props(不用加 props.):

&lt;template>
  &lt;h2>{{ title }}&lt;/h2>
  &lt;p>数量:{{ count }}&lt;/p>
&lt;/template>


五、Props 是只读的

⚠️ 不能修改 props 值!

props.count++ // ❌ 报错

如果要修改,可以复制成本地响应式变量:

import { ref } from 'vue'

const count = ref(props.count)
count.value++

或者通过事件通知父组件更新。


六、父组件传值示例

父组件(App.vue)

&lt;template>
  &lt;Child :title="msg" :count="5" />
&lt;/template>

&lt;script setup>
const msg = '来自父组件的标题'
&lt;/script>

子组件(Child.vue)

&lt;script setup>
const props = defineProps({
  title: String,
  count: Number
})
&lt;/script>

&lt;template>
  &lt;h3>{{ title }} - {{ count }}&lt;/h3>
&lt;/template>


七、结合 defineEmits(父子通信)

子组件可以通过 emit 通知父组件更新:

&lt;script setup>
const props = defineProps({ count: Number })
const emit = defineEmits(['update-count'])

const add = () => emit('update-count', props.count + 1)
&lt;/script>

父组件监听:

&lt;Child :count="count" @update-count="count = $event" />


八、进阶:v-model 的 Props

在 Vue 3 中,v-model 本质是 modelValue + update:modelValue

子组件

&lt;script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])

const update = () => emit('update:modelValue', props.modelValue + 1)
&lt;/script>

&lt;template>
  &lt;p>{{ modelValue }}&lt;/p>
  &lt;button @click="update">增加&lt;/button>
&lt;/template>

父组件

&lt;Child v-model="count" />

这等价于:

&lt;Child :modelValue="count" @update:modelValue="count = $event" />


九、Props 校验示例

你也可以为 props 设置自定义校验函数:

&lt;script setup>
const props = defineProps({
  level: {
    type: Number,
    validator: v => v >= 1 &amp;&amp; v &lt;= 5
  }
})
&lt;/script>


🔟 Props 声明方式对比总结

声明方式特点是否支持默认值是否支持类型检查
数组写法简洁、无验证
对象写法支持验证、默认值✅(运行时)
TypeScript 类型最现代、推荐✅(需 withDefaults)✅(编译时)

推荐实践(现代 Vue3 项目写法)

&lt;script setup lang="ts">
interface Props {
  title?: string
  count?: number
  isActive?: boolean
}

const props = withDefaults(defineProps&lt;Props>(), {
  title: '默认标题',
  count: 0,
  isActive: true
})
&lt;/script>

&lt;template>
  &lt;div>
    &lt;h2>{{ title }}&lt;/h2>
    &lt;p>{{ count }}&lt;/p>
  &lt;/div>
&lt;/template>