首页 > 编程笔记 > JavaScript笔记
阅读:49
Vue props属性的用法(非常详细)
Vue 的父组件与子组件可以通过 props 属性传递的方式实现交互,其中分为简单数组接收、简单对象接收和复杂对象接收 3 种模式,下面分别进行介绍。

图 1 父与子关系模式
1) 在 App 父组件中,当 HelloWorld 子组件被调用时设置属性并传递。比如给 HelloWorld 子组件设置 msg 与 count 两个属性,并且给 msg 属性传递值“你好,世界!”,count 属性传递值“0”。
此时 App.vue 文件代码如下:
2) 在子组件中需要接收父组件传递的属性 msg 和 count。利用 defineProps 即可实现属性的接收,因为有多个属性,所以可以利用数组接收属性。
此时可以直接在子组件中使用接收的属性值,比如通过插值表达式渲染和累加 count 属性的值,实现代码如下:
直接定义 increase 函数,并通过 "count.value+++" 实现对 count 值的累加。修改后的 components/HelloWorld.vue 文件代码如下:
开发者可能会想,如果将 defineProps 接收的属性通过变量对象来接收,并利用对象属性的方式获取是不是可以呢?下面依旧通过代码来验证。
只修改 components/HelloWorld.vue 文件中的 script 脚本部分,代码如下:

图 2 控制台出现警告提示
那么应如何在 script 脚本中操作 defineProps 接收的数据呢?答案是:先将数据中转,然后获取。
比如在子组件中声明一个 ref 响应式数据 update,将其初始值设置为 defineProps 接收的 count 属性值,在 increase() 函数中通过“update.value++”进行累加处理,并在模板中进行渲染,实现代码如下:
读者也可将父组件中传递的值进行任意修改来查看页面效果,比如将父组件中的子组件重新编写为“<HelloWorld msg="你好,世界!"count="8"/>”,从而确认 update 的初始值显示是否也随之更改为“8”。
细心的读者会发现,在简单数组接收模式中,我们无法判别传递的 count 属性和 msg 属性的类型。显然,msg 是字符串类型的,那么这是否意味着 count 也是字符串类型的呢?可是根据我们想得到的 count 值,其显然是数值类型的数据,而程序在运行的时候却没有给出任何的警告提示或者报错。
现在将于组件中的 defineProps 属性接收方式修改为简单对象模式,并查看效果。
将 components/HelloWorld.vue 文件中的 script 脚本部分修改为下方代码:

图 3 警告提示
虽然运行结果没有发生变化,但类型不对应还是存在一定的隐患的。这里可以在父组件中通过 v-bind 指令将 count 属性值绑定为数值类型的值来解决该问题。
试想父组件在调用子组件并设置属性时,遗漏了某个属性的设置,比如设置为“<HelloWorld msg="你好,世界!"/>”,遗漏了 count 属性,而在子组件中又接收和使用了 count 属性,此时运行程序,count 属性会得到“NaN”的结果,但控制台不会报错。显然,运行结果与预期结果是不一致的。
此时就可以利用 defineProps 复杂对象接收模式进行优化。将 count 属性设置为对象类型,其属性值主要包括 type(数据类型)、default(默认值)、required(是否必须传递)、validator(自定义校验规则)这 4 个部分。
将上面的代码进行修改,修改后的 components/HelloWorld.vue 文件代码如下:
只不过控制台中还会出现“Missing required prop: "count"”的警告提示,这是因为 count 属性在接收时,限制其 required 为“true”。
如果在 HelloWorld 子组件中定义接收 count 属性,将其默认值设置为 7,运行程序,则控制台中会出现无效属性的警告提示,如下图所示。

图 4 控制台中出现无效属性的警告提示
因为上面的代码中同样设置了自定义校验规则,要求 count 属性值大于 0 且小于 3,而当前“7”显然不在此范围内。

图 1 父与子关系模式
Vue props简单数组接收模式
从父组件的设置与传递属性到子组件的接收与使用属性的整个过程可以划分成两个部分。1) 在 App 父组件中,当 HelloWorld 子组件被调用时设置属性并传递。比如给 HelloWorld 子组件设置 msg 与 count 两个属性,并且给 msg 属性传递值“你好,世界!”,count 属性传递值“0”。
此时 App.vue 文件代码如下:
<script setup> import HelloWorld from './components/HelloWorld.vue'; </script> <template> <HelloWorld msg="你好,世界!" count="0" /> </template>
2) 在子组件中需要接收父组件传递的属性 msg 和 count。利用 defineProps 即可实现属性的接收,因为有多个属性,所以可以利用数组接收属性。
此时可以直接在子组件中使用接收的属性值,比如通过插值表达式渲染和累加 count 属性的值,实现代码如下:
<template> <div> <p>{{ msg }}</p> <p>count:{{ count }}</p> <button @click="count++">count++</button> </div> </template> <script setup> import HelloWorld from './components/HelloWorld.vue'; </script>在上面的代码中,count 属性值是直接在模板中进行累加的,并不是通过创建 increase 函数进行累加的。如果想在子组件中创建一个 increase 函数实现累加,那么能不能像之前一样直接编写呢?下面来尝试实现一下。
直接定义 increase 函数,并通过 "count.value+++" 实现对 count 值的累加。修改后的 components/HelloWorld.vue 文件代码如下:
<template> <div> <p>{{ msg }}</p> <p>count:{{ count }}</p> <button @click="count++">count++</button> <button @click="increase">increase</button> </div> </template> <script setup> defineProps(['msg', 'count']); const increase = () => { count.value++; }; </script>运行代码后,会报“count is not defined”的错误提示。
开发者可能会想,如果将 defineProps 接收的属性通过变量对象来接收,并利用对象属性的方式获取是不是可以呢?下面依旧通过代码来验证。
只修改 components/HelloWorld.vue 文件中的 script 脚本部分,代码如下:
<script setup> const props = defineProps(['msg', 'count']); const increase = () => { props.count++; }; </script>上面的代码利用 props 进行接收,但运行后页面依旧出现警告提示,如下图所示:

图 2 控制台出现警告提示
那么应如何在 script 脚本中操作 defineProps 接收的数据呢?答案是:先将数据中转,然后获取。
比如在子组件中声明一个 ref 响应式数据 update,将其初始值设置为 defineProps 接收的 count 属性值,在 increase() 函数中通过“update.value++”进行累加处理,并在模板中进行渲染,实现代码如下:
<template> <div> <p>{{ msg }}</p> <p>count:{{ count }}</p> <p>update:{{ update }}</p> <button @click="count++">count++</button> <button @click="increase">increase</button> </div> </template> <script setup> import { ref } from 'vue'; const props = defineProps(['msg', 'count']); const update = ref(props.count); const increase = () => { update.value++; }; </script>此时不会报任何错误提示和警告提示,效果成功实现。
读者也可将父组件中传递的值进行任意修改来查看页面效果,比如将父组件中的子组件重新编写为“<HelloWorld msg="你好,世界!"count="8"/>”,从而确认 update 的初始值显示是否也随之更改为“8”。
Vue props简单对象接收模式
如果只是用简单数组接收属性,我们是无法判别属性的类型的。细心的读者会发现,在简单数组接收模式中,我们无法判别传递的 count 属性和 msg 属性的类型。显然,msg 是字符串类型的,那么这是否意味着 count 也是字符串类型的呢?可是根据我们想得到的 count 值,其显然是数值类型的数据,而程序在运行的时候却没有给出任何的警告提示或者报错。
现在将于组件中的 defineProps 属性接收方式修改为简单对象模式,并查看效果。
将 components/HelloWorld.vue 文件中的 script 脚本部分修改为下方代码:
<script setup> import { ref } from 'vue'; const props = defineProps({ msg: String, count: Number, }); const update = ref(props.count); const increase = () => { update.value++; }; </script>此时我们将接收的类型限制为数值类型,由于没有修改 App.vue 中的代码,默认传递的是字符串类型的数据,所以子组件在接收的时候对属性进行了类型的检测,并在控制台中给出警告提示,如下图所示:

图 3 警告提示
虽然运行结果没有发生变化,但类型不对应还是存在一定的隐患的。这里可以在父组件中通过 v-bind 指令将 count 属性值绑定为数值类型的值来解决该问题。
Vue props复杂对象接收模式
简单数组接收模式仅能实现属性接收但无法进行类型约束,而简单对象接收模式不仅可以接收属性还能约束类型,但这样的功能是否已经足够了呢?试想父组件在调用子组件并设置属性时,遗漏了某个属性的设置,比如设置为“<HelloWorld msg="你好,世界!"/>”,遗漏了 count 属性,而在子组件中又接收和使用了 count 属性,此时运行程序,count 属性会得到“NaN”的结果,但控制台不会报错。显然,运行结果与预期结果是不一致的。
此时就可以利用 defineProps 复杂对象接收模式进行优化。将 count 属性设置为对象类型,其属性值主要包括 type(数据类型)、default(默认值)、required(是否必须传递)、validator(自定义校验规则)这 4 个部分。
将上面的代码进行修改,修改后的 components/HelloWorld.vue 文件代码如下:
<script setup> import { ref } from 'vue'; const props = defineProps({ msg: String, count: { type: Number, // 约束类型 default: 7, // 设置默认值 required: true, // 是否必须传递 validator: (val) => val > 0 && val < 3, // 自定义校验规则 }, }); const update = ref(props.count); const increase = () => { update.value++; }; </script>虽然父组件在调用 HelloWorld 子组件时没有设置和传递 count 属性,但由于在子组件中利用复杂对象接收模式设置了 count 属性的类型、默认值及是否必须传递等属性,所以页面中显示的结果不会出错,能够与预期结果达成一致。
只不过控制台中还会出现“Missing required prop: "count"”的警告提示,这是因为 count 属性在接收时,限制其 required 为“true”。
如果在 HelloWorld 子组件中定义接收 count 属性,将其默认值设置为 7,运行程序,则控制台中会出现无效属性的警告提示,如下图所示。

图 4 控制台中出现无效属性的警告提示
因为上面的代码中同样设置了自定义校验规则,要求 count 属性值大于 0 且小于 3,而当前“7”显然不在此范围内。