首页 / Vue3 入门教程 / Props 详解

Vue3 入门教程

Props 详解

本教程共 40 篇 · 第 15 篇 · 更新于 2026-07-29 · 约 8 分钟阅读

VueVue3 入门教程Props组件通信类型验证单向数据流

15. Props 详解

本节目标:掌握 Props 的完整用法,包括声明、验证、单向数据流和命名规范,让你的组件接口清晰可靠。

Props 是什么

Props 是父组件传递给子组件的自定义属性。你可以把它理解为函数的参数——父组件传入什么,子组件就接收什么。

Props 的声明方式

<script setup> 中,使用 defineProps() 宏来声明:

<script setup>
// 数组语法——简单但不验证类型
defineProps(['title', 'likes'])
</script>

数组写法很方便,但没法告诉别人这个 prop 应该是什么类型。实际项目中更推荐对象语法:

<script setup>
// 对象语法——可以指定类型
defineProps({
  title: String,
  likes: Number
})
</script>

对象语法不只是文档——如果你传错了类型,Vue 会在浏览器控制台发出警告。

运行时验证

对象语法的真正威力在于验证。你可以为每个 prop 指定详细的规则:

defineProps({
  // 基础类型检查
  propA: Number,

  // 允许多种类型
  propB: [String, Number],

  // 必填字符串
  propC: {
    type: String,
    required: true
  },

  // 带默认值的数字
  propE: {
    type: Number,
    default: 100
  },

  // 对象类型的默认值——必须用工厂函数
  propF: {
    type: Object,
    default(rawProps) {
      return { message: 'hello' }
    }
  },

  // 自定义验证函数
  propG: {
    validator(value, props) {
      return ['success', 'warning', 'danger'].includes(value)
    }
  },

  // 函数类型的默认值
  propH: {
    type: Function,
    // 对象和数组不同,这里是直接返回默认函数
    default() {
      return 'Default function'
    }
  }
})
Note

对象和数组的默认值必须用工厂函数返回,不能直接写对象字面量。这是为了避免多个组件实例共享同一个引用。

验证规则一览

验证选项说明
type期望的类型(原生构造函数或自定义类)
required是否为必填
default默认值(对象/数组必须用工厂函数)
validator自定义验证函数,返回 true/false

type 可以是以下原生构造函数:StringNumberBooleanArrayObjectDateFunctionSymbolError

也可以是你自己的类,Vue 会用 instanceof 来检查。

可空类型

如果 prop 必填但允许 null,用数组语法包含 null

defineProps({
  id: {
    type: [String, null],
    required: true
  }
})
Warning

如果 type 只写 null 而不用数组语法,那将允许任何类型通过。

命名约定

JavaScript 中用 camelCase,模板中用 kebab-case:

// 组件内声明用 camelCase
defineProps({
  greetingMessage: String
})
<!-- 父组件传递时用 kebab-case -->
<MyComponent greeting-message="hello" />

为什么这样设计?camelCase 在 JavaScript 里是合法的标识符,可以直接在模板表达式里用。而 kebab-case 和 HTML 属性的命名习惯一致。

静态 vs 动态 Props

静态 prop 直接写值:

<BlogPost title="My journey with Vue" />

动态 prop 用 v-bind(缩写 :):

<!-- 绑定变量 -->
<BlogPost :title="post.title" />

<!-- 绑定表达式 -->
<BlogPost :title="post.title + ' by ' + post.author.name" />

传递不同类型的值

数字——不加 v-bind 会被当字符串:

<!-- 错误:传的是字符串 "42" -->
<BlogPost likes="42" />

<!-- 正确:传的是数字 42 -->
<BlogPost :likes="42" />

布尔值——只写属性名表示 true

<!-- 等价于 :is-published="true" -->
<BlogPost is-published />

<!-- 传 false 必须用 v-bind -->
<BlogPost :is-published="false" />

数组和对象——必须用 v-bind

<BlogPost :comment-ids="[234, 266, 273]" />

<BlogPost :author="{ name: 'Veronica', company: 'Veridian Dynamics' }" />

用一个对象批量传 prop

v-bind 不跟属性名,会把对象的所有属性都传进去:

const post = {
  id: 1,
  title: 'My Journey with Vue'
}
<!-- 等价于 :id="post.id" :title="post.title" -->
<BlogPost v-bind="post" />

单向数据流

这是 Vue 组件通信的第一原则:prop 只能从父组件流向子组件,反过来不行

每次父组件更新,子组件的 prop 都会刷新为最新值。如果你尝试在子组件里修改 prop,Vue 会警告你:

const props = defineProps(['foo'])

// ❌ 警告!prop 是只读的
props.foo = 'bar'

想修改 prop 怎么办

有两种常见场景。

场景一:prop 只是初始值——用 ref 断开连接:

const props = defineProps(['initialCounter'])

// counter 只用 props.initialCounter 作为初始值
// 后续不再跟随 prop 更新
const counter = ref(props.initialCounter)

场景二:需要对 prop 做转换——用计算属性:

const props = defineProps(['size'])

// 自动跟随 prop 更新
const normalizedSize = computed(() => props.size.trim().toLowerCase())

对象和数组的特殊情况

JavaScript 中对象和数组是引用传递。子组件虽然不能替换整个 prop,但可以修改其内部的属性:

// 子组件内部
props.foo.bar = 'baz' // 技术上可行

这样做会让数据流变得不清晰。最佳实践是:要么用 readonly() 保护数据,要么让子组件 emit 事件通知父组件来修改。

Boolean 强制转换

声明为 Boolean 类型的 prop 有特殊转换规则:

defineProps({
  disabled: Boolean
})
<!-- 等价于 :disabled="true" -->
<MyComponent disabled />

<!-- 等价于 :disabled="false" -->
<MyComponent />

当 prop 允许多个类型时,Boolean 的转换规则取决于顺序——Boolean 在 String 前面才会生效

// disabled 会被强制转换为 true
defineProps({ disabled: [Boolean, Number] })
defineProps({ disabled: [Boolean, String] })

// 不会触发强制转换,disabled 会按 Number 类型解析
defineProps({ disabled: [Number, Boolean] })

// disabled 会被解析为空字符串 ""
defineProps({ disabled: [String, Boolean] })
Tip

Boolean 强制转换在 String 之前才生效。[Boolean, String] 转换,[String, Boolean] 不转换。[Number, Boolean] 也不会触发强制转换。

本节回顾

  • Props 用 defineProps() 声明,推荐对象语法做类型验证
  • 验证选项包括 typerequireddefaultvalidator
  • prop 命名:JavaScript 用 camelCase,模板用 kebab-case
  • 单向数据流——prop 只读,修改用本地 ref 或 computed
  • Boolean 类型的 prop 有特殊强制转换规则,注意和 String 的顺序