当前位置: 首页> 游戏> 单机 > props与defineProps

props与defineProps

时间:2025/7/18 17:23:48来源:https://blog.csdn.net/qq_40792800/article/details/141831363 浏览次数:0次

在 Vue3 中,script 脚本存在两种情况。一种是 setup 函数,一种是 <script setup>。而针对这两种不同情况,Vue 也存在 props 和 defineProps 两种接收父组件传毒数据的形式。

首先,默认已掌握 Vue2 的父子组件 props 传参,然后进行下面的过程。

setup () {} 函数模式

其实在第一章 拉开序幕的 setup 中,解释了 在 setup 函数中,props 的使用方式。

首先定义父组件,通过reactive 定义响应式数据且返回。然后在父组件中引入子组件 <Child>,将响应式数据 person 对象通过 props 方式传递到子组件中。

<template><Child :person="person" />
</template><script>
import Child from "./components/Child.vue";
import { reactive } from "vue";export default {name: "App",components: {Child,},setup() {let person = reactive({name: "al",age: 29,});return {person};},
};
</script>

然后定义子组件

<template><div>{{ person }}</div>
</template><script>
export default {name: 'ChildComponent',setup(props) {console.log(props,'props');}
}
</script>

在 setup 函数中,接收两个参数,第一个就是 props。但是,此时如果直接打印该 props,发现值是一个空对象,且控制台报错。

这是因为,如果使用的是 setup 函数模式,需要像Vue2一样,先通过 props 属性接收,然后才能在 setup 函数中 接收到 props 

export default {name: 'ChildComponent',props: ['person'],setup(props) {console.log(props,'props');}
}

setup 函数 + ts

上面说的是最基础的 props 数据传递,在Vue3 中更好的支持了ts,以此来限制类型,提高代码质量。所以我们可以通过 ts 来规定参数类型。

// lang 需要配置,表示支持 ts 语法
<script lang="ts">
import Child from "./components/Child.vue";
import { reactive } from "vue";// 通过 interface 定义接口类型
interface Person {name: string,age: number,
}export default {name: "App",components: {Child,},setup() {// 直接调用 Person 接口,以此来控制类型let person:Person = reactive({name: "al",age: 29,});return {person};},
};
</script>

如果,reactive 定义的数据与 Person 接口存在区别,那么 TS 则会飘红报错,例如:我把对象数据的 name 属性故意写错成 ne属性,vs code 则给了警告

当然,我们可以写的更优雅一点,因为 reactive 本身是可以携带泛型的,所以可以写成

// 通过泛型来规范数据
let person = reactive<Person>({name: "al",age: 29,
});

然后再子组件中通过 props 接收时通过断言的形式指定属性的类型,通过defult指定默认值

props: {person: {type: Object as () => { name: string; age: number },default: () => ({name: "al",age: 29,}),},
},

到了这一步,就算是完成了 setup 函数 + TS 的编写。

 <script setup>

<script setup> 模式中是不存在 setup 函数的,当然也不能配置 props 属性。<script setup>里面的代码会被编译成组件中 setup() 函数的内容。

那么现在问题来了,我需要怎么接收父组件传递的 props,以及怎么使用该 props 数据呢?

父组件:数据不变,TS类型不变,改为  <script setup> 形式

<template><Child :person="person" />
</template><script lang="ts" setup>
import Child from "./components/Child.vue";
import { reactive } from "vue";interface Person {name: string;age: number;
}let person = reactive<Person>({name: "al",age: 29,
});
</script>

子组件:Vue3 提供了 一个新的 API -- defineProps 用来接收父组件传递的props 数据。defineProps 是一个函数,接收一个数组参数,数组内部的元素则是父组件传递过来的数据,每个元素都是字符串形式

<template><div>{{ person }}</div>
</template><script lang="ts" setup>
import { defineProps } from 'vue'defineProps(['person'])</script>

展示效果:数据正确展示

父组件传递多个数据

<template><Child :person="person" new="newValue" old="oldValue"/>
</template>

子组件只需要在数组中新增元素即可

defineProps(['person','new','old'])

 展示效果:

Vue3 中的 defineProps() 函数返回一个 Proxy 对象,该对象内部包含的是 defineProps() 函数 中接收的 props 数据,可以针对于 props 中的数据进行某些代码逻辑判断。例如

<script lang="ts" setup>
import { defineProps } from 'vue'let x = defineProps(['person','new','old'])if (x.person.age > 1) {console.log(x);
}
</script>

展示效果:

到此为止,defineProps() 函数的基本使用就完成了,那如果此时我也想通过 TS 来规范数据类型又需要怎么做呢?

 <script setup> + TS

把上面的数据改一下,现在父组件传递的不是一个对象,而是一个数组。数组内部则是个人信息

<template><Person :list="persons" />
</template><script lang="ts" setup name="App">
import Person from "./components/Child.vue";
import { reactive } from "vue";let persons = reactive([{ id: "e98219e12", name: "张三", age: 18 },{ id: "e98219e13", name: "李四", age: 19 },{ id: "e98219e14", name: "王五", age: 20 },
]);
</script>

现在需要对父组件中的数据进行 TS 类型限制。我们可以在当前文件中直接写,但是更建议是新开一个文件专门用来写 TS 类型。例如,在 src 目录下新建 types 文件夹,然后新建 index.ts 文件。

// 定义一个接口,限制每个Person对象的格式
export interface Person {id: string,name: string,age: number
}// 定义一个自定义类型
// export type Persons = Array<Person>// 简写的自定义类型
export type Persons = Person[]

父组件中根据 接口 和 自定义类型 来规范数据格式

<script lang="ts" setup name="App">
import Person from "./components/Person.vue";
import { reactive } from "vue";// 引入类型时需要使用 type 声明,之前版本的ts是不需要的
import { type Persons } from "@/types";    // 通过泛型规范 persons 数据类型
let persons = reactive<Persons>([{ id: "e98219e12", name: "张三", age: 18 },{ id: "e98219e13", name: "李四", age: 19 },{ id: "e98219e14", name: "王五", age: 20 },
]);
</script>

 在子组件中 通过 defineProps 接收数据

const props = defineProps(['list'])

在子组件中 通过 defineProps 接收数据 + 限制类型:通过泛型限制数据类型

// 引入类型时需要使用 type 声明,之前版本的ts是不需要的
import { type Persons } from "@/types"; const props = defineProps<{list:Persons}>()

在子组件中 通过 defineProps 接收数据 + 限制类型 + 是否必须

// 引入类型时需要使用 type 声明,之前版本的ts是不需要的
import { type Persons } from "@/types"; // 通过 ? 表示该值不是必须值
const props = defineProps<{list?:Persons}>()

在子组件中 通过 defineProps 接收数据 + 限制类型 + 是否必须 + 指定默认值。此时需要引入新的 API --  withDefaults。该 API 也是一个函数,接收两个参数,第一个是 接收数据 + 限制类型 + 是否必须 的集合体,第二个就是指定的默认值。且默认值必须通过函数返回(类似于Vue2中的默认值)。

import {defineProps,withDefaults} from 'vue'
import {type Persons} from '@/types'let props = withDefaults(defineProps<{list?:Persons}>(),{ list:()=>[{id:'asdasg01',name:'小猪佩奇',age:18}]}
)

总结

在Vue3 中接收父组件传递的 props 数据存在两种方式

  1. 通过配置式的props ,且使用数组形式 接收父组件传递的数据,然后在 setup 中通过 props 参数获取接收到的数据进行逻辑处理。不处理也可以直接使用。;例如:props : ['a','b','c']
  2. 通过 <script setup> 形式,使用 defineProps() 来接收父组件传递数据,defineProps() 函数接收一个字符串形式的数组,类似['a','b','c'],数组中每一项就是父组件传递的数据。写在 <script setup> 中的代码最终会被编译到 setup() 函数中。例如:defineProps(['list','a','b'])

通过 TS  限制参数类型 + 指定默认值 + 限制必要性 也存在两种方式

  1. 通过配置式的props,且使用对象形式 来接收父组件传递的数据,然后通过配置项来限制
    props: {person: {// 使用断言控制参数类型type: Object as () => { name: string; age: number },// 通过函数返回默认值,一般只有对象或数组才会如此,基本类型直接写值即可default: () => ({name: "al",age: 29,}),// 是否必须isRequied:false},
    },
  2. 通过 <script setup> 形式,使用 defineProps() 来接收父组件传递数据,通过泛型来限制数据类型和是否必须,通过 withDefaults() 设置默认值 

    let props = withDefaults(defineProps<{list?:Persons}>(),{list:() =>[{id:'asdasg01',name:'小猪佩奇',age:18}]
    })
关键字:props与defineProps

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: