props
前言
props
是 Vue 组件的重要机制,用于父组件向子组件传递数据。在开发组件化应用时,组件之间的通信变得非常重要,而 props
是解决这个问题的主要方式。props
使得父组件能够通过属性传递数据到子组件,子组件通过声明 props
来接收和使用这些数据。
# 1. 什么是 props
props
是 Vue 组件的一种机制,允许父组件向子组件传递数据。子组件声明自己希望接收的 props
,然后父组件通过绑定属性来提供这些数据。props
是单向的,这意味着数据只能从父组件流向子组件,子组件不能直接修改父组件传递的 props
,否则 Vue 会警告你。这种单向数据流的特性提高了应用的可维护性和代码的可靠性。
示例:
<!-- 父组件 -->
<template>
<!-- 使用 `:` 绑定 props -->
<ChildComponent :title="articleTitle" :likes="articleLikes" />
</template>
<script setup>
const articleTitle = "Vue 3 教程"; // 父组件中的数据
const articleLikes = 123;
</script>
2
3
4
5
6
7
8
9
10
在这个示例中,title
和 likes
作为 props
从父组件传递给子组件。
# 2. 在 Vue 3 中定义 props
在 Vue 3 中,<script setup>
提供了一种更简洁的方式来定义和使用 props
。我们使用 defineProps
函数来声明子组件需要接收的 props
。
# 2.1 defineProps
函数
defineProps
是一个宏函数,用于在 <script setup>
中声明组件接收的 props
。它返回一个包含所有传入 props
的对象,并可以通过以下几种方式来定义和声明 props
。
语法:
const props = defineProps([propName1, propName2, ...])
或者:
const props = defineProps({
propName1: propType1,
propName2: propType2,
...
})
2
3
4
5
# 示例 1:使用字符串数组定义 props
如果只想声明接收的 props
名字,可以使用字符串数组。
<script setup>
const props = defineProps(['title', 'likes']); // 定义接收的 props 名称
console.log(props.title); // 访问传入的 'title'
console.log(props.likes); // 访问传入的 'likes'
</script>
<template>
<div>
<h1>{{ props.title }}</h1>
<p>Likes: {{ props.likes }}</p>
</div>
</template>
2
3
4
5
6
7
8
9
10
11
12
# 示例 2:使用对象定义 props
类型
你也可以通过对象的形式来声明 props
的名称和类型,以确保传入的数据是正确的类型。
<script setup>
const props = defineProps({
title: String, // title 是字符串类型
likes: Number // likes 是数字类型
});
console.log(props.title); // 访问传入的 'title'
console.log(props.likes); // 访问传入的 'likes'
</script>
<template>
<div>
<h1>{{ props.title }}</h1>
<p>Likes: {{ props.likes }}</p>
</div>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 2.2 使用 TypeScript 声明 props
如果你在使用 TypeScript,可以直接通过泛型来声明 props
的类型,这样能够提供更强的类型检查。
<script setup lang="ts">
const props = defineProps<{ title: string; likes: number }>(); // 声明 title 为字符串,likes 为数字
console.log(props.title); // TypeScript 会自动提供类型提示
console.log(props.likes);
</script>
<template>
<div>
<h1>{{ props.title }}</h1>
<p>Likes: {{ props.likes }}</p>
</div>
</template>
2
3
4
5
6
7
8
9
10
11
12
通过使用 TypeScript 泛型,我们能够让 Vue 的 props
机制更加严格,确保传入的数据是预期的类型,减少运行时错误。
# 3. 为 props
设置默认值
在开发中,父组件有时不会传递所有的 props
,为了保证组件可以正常工作,我们可以为 props
提供默认值。Vue 3 提供了 withDefaults()
函数来处理这种情况。
# 3.1 withDefaults
函数
withDefaults()
用于为 defineProps()
定义的 props
设置默认值。如果父组件没有传递某个 props
,则会使用默认值。
const props = withDefaults(defineProps({
title: String,
likes: Number
}), {
title: '默认标题', // 默认值
likes: 0 // 默认值
});
2
3
4
5
6
7
# 示例:设置默认值
<script setup>
import { withDefaults, defineProps } from 'vue';
// 使用 withDefaults 设置 props 的默认值
const props = withDefaults(defineProps({
title: String,
likes: Number
}), {
title: '默认标题', // 如果父组件没有传递 title,则使用 '默认标题'
likes: 0 // 如果父组件没有传递 likes,则使用 0
});
</script>
<template>
<div>
<h1>{{ props.title }}</h1>
<p>Likes: {{ props.likes }}</p>
</div>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 4. 父组件如何向子组件传递 props
在父组件中,我们通过 :
语法将数据从父组件传递给子组件。:
代表动态绑定,传递的是一个变量或表达式的结果。
<template>
<!-- 父组件通过 : 绑定 props -->
<ChildComponent :title="articleTitle" :likes="articleLikes" />
</template>
<script setup>
const articleTitle = "我的文章"; // 父组件的数据
const articleLikes = 120;
</script>
2
3
4
5
6
7
8
9
在子组件中,我们使用 defineProps
函数接收这些 props
。
# 5. 使用 props
的注意事项
# 5.1 Prop 名字的格式
在 Vue 中,props
的名字应当使用不同的命名格式,具体取决于你在模板中如何使用:
- 在模板中:使用
kebab-case
(短横线形式)。 - 在 JavaScript/TypeScript 中:使用
camelCase
。
示例:
<!-- 父组件中传递 props,使用 kebab-case -->
<ChildComponent greeting-message="Hello, Vue 3!" />
2
// 在子组件中,接收 props 时使用 camelCase
const props = defineProps({
greetingMessage: String
});
2
3
4
# 5.2 静态和动态 props
静态传递
props
:直接传递固定值。<ChildComponent title="静态标题" />
1动态传递
props
:使用变量或表达式传递动态值。<ChildComponent :title="dynamicTitle" />
1
# 6. props
的类型校验
Vue 支持对 props
进行类型检查,可以通过指定类型来限制传入数据的类型。你可以使用多种内置类型进行校验,如 String
、Number
、Boolean
、Array
、Object
等,还可以设置默认值和自定义校验函数。
# 示例:props
类型校验
<script setup>
const props = defineProps({
// title 必须是 String 类型,并且是必须传递的
title: {
type: String,
required: true
},
// likes 是 Number 类型,有一个默认值
likes: {
type: Number,
default: 0
},
// 使用自定义校验函数
status: {
type: String,
validator(value) {
// 只允许 'success', 'error', 'warning' 作为有效值
return ['success', 'error', 'warning'].includes(value);
}
}
});
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 7. 使用对象一次性传递多个 props
有时你可能会想要一次性传递多个 props
,这时可以使用 v-bind
语法来将一个对象中的所有属性都传递给子组件。
<template>
<!-- 使用对象绑定多个 props -->
<ChildComponent v-bind="article" />
</template>
<script setup>
const article = {
title: "Vue 3 教程",
likes: 500
};
</script>
2
3
4
5
6
7
8
9
10
11
在这个示例中,article
对象中的 title
和 likes
被作为 props
传递给了 ChildComponent
。
# 8. Prop 名称冲突
Vue 会自动将 props
名字与 HTML 原生属性进行合并处理,但如果有冲突,Vue 会优先
解析自定义的 props
,以确保自定义属性不被覆盖。
# 9. 使用 props
的最佳实践
- 使用明确的
props
定义:确保你明确声明了每个props
的名称、类型和是否为必填项。这样可以提高组件的可维护性和可读性。 - 为可选的
props
设置默认值:通过withDefaults
或默认值机制,为可选的props
提供默认值,避免组件因未接收到props
而无法正常工作。 - 尽量避免修改
props
的值:props
是只读的,子组件不应该直接修改传入的props
,否则会违反 Vue 的单向数据流原则。
# 10. props
的完整示例
# 父组件
<template>
<ChildComponent :title="articleTitle" :likes="articleLikes" />
</template>
<script setup>
const articleTitle = "深入了解 Vue 3 的 Props";
const articleLikes = 300;
</script>
2
3
4
5
6
7
8
# 子组件
<template>
<div>
<h1>{{ title }}</h1>
<p>Likes: {{ likes }}</p>
</div>
</template>
<script setup>
const props = defineProps({
title: {
type: String,
required: true // title 是必须传递的
},
likes: {
type: Number,
default: 0 // 默认值为 0
}
});
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
总结
props
是 Vue 组件之间数据传递的主要机制,确保组件能够动态接收外部数据。defineProps()
提供了一种简洁的方式来声明子组件接收的props
,并能够通过 TypeScript 进行类型检查,提升了代码的安全性和可维护性。withDefaults()
函数为props
提供默认值,确保组件在未接收到父组件的数据时依然能够正常工作。- Vue 通过 单向数据流 提高了组件的可预测性和稳定性,减少了数据流动中的副作用,使得组件之间的通信更加明确清晰。