Skip to content

Vue Props

在 Vue 中,父组件通过 Props 向子组件传递数据。Props 是你可以在组件上注册的一些自定义 attribute。当一个值传递给一个 prop attribute 的时候,它就变成了那个组件实例的一个 property。

传递 Props

假设我们有一个博客文章组件 BlogPost.vue,我们希望从父组件 App.vue 向它传递文章的标题。

BlogPost.vue (子组件)

vue
<script setup>
// 使用 defineProps 宏来声明 props
const props = defineProps(['title'])

// props.title 可以在模板和脚本中访问
console.log(props.title)
</script>

<template>
  <h4>{{ title }}</h4>
</template>

App.vue (父组件)

vue
<script setup>
import BlogPost from './BlogPost.vue'
</script>

<template>
  <BlogPost title="My journey with Vue" />
  <BlogPost title="Blogging with Vue" />
  <BlogPost title="Why Vue is so fun" />
</template>

在这个例子中:

  1. 子组件 BlogPost.vue 使用 defineProps(['title']) 宏来声明它接收一个名为 title 的 prop。
  2. 父组件 App.vue 在使用 <BlogPost> 组件时,像传递 HTML attribute 一样,将一个字符串传递给 title prop。

Prop 命名规则

  • CamelCase vs. kebab-case: 在 JavaScript 中,prop 名称通常使用驼峰式 (camelCase),如 greetingText。但在 HTML attribute 中,推荐使用短横线分隔式 (kebab-case),如 greeting-text。Vue 会自动处理这两种命名风格之间的转换。

    js
    // JS 中
    defineProps(['greetingText'])
    html
    <!-- HTML 中 -->
    <MyComponent greeting-text="hello" />

动态 Props

类似于绑定普通的 HTML attribute,我们也可以使用 v-bind (或其简写 :) 来动态地传递 props。

vue
<script setup>
import { ref } from 'vue'
import BlogPost from './BlogPost.vue'

const posts = ref([
  { id: 1, title: 'My journey with Vue' },
  { id: 2, title: 'Blogging with Vue' },
  { id: 3, title: 'Why Vue is so fun' }
])
</script>

<template>
  <BlogPost
    v-for="post in posts"
    :key="post.id"
    :title="post.title"
  />
</template>

Prop 校验

组件可以为 props 指定校验要求,例如类型检查。如果传入的值不满足要求,Vue 会在浏览器控制台中给出警告。

要指定校验,你可以向 defineProps 提供一个带有校验要求的对象,而不是一个字符串数组。

vue
<script setup>
defineProps({
  // 基础的类型检查
  // (`null` 和 `undefined` 会通过任何类型验证)
  propA: Number,
  // 多个可能的类型
  propB: [String, Number],
  // 必填的字符串
  propC: {
    type: String,
    required: true
  },
  // 带默认值的数字
  propD: {
    type: Number,
    default: 100
  },
  // 带默认值的对象
  propE: {
    type: Object,
    // 对象或数组的默认值必须从一个工厂函数返回
    default: () => ({ message: 'hello' })
  },
  // 自定义校验函数
  propF: {
    validator: (value) => {
      // 这个值必须匹配下列字符串中的一个
      return ['success', 'warning', 'danger'].includes(value)
    }
  }
})
</script>

单向数据流

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。

每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在控制台给出警告。