一文詳析vue3?Props的用法(父?jìng)髯?
在 Vue 3 中,Props(屬性)用于在組件之間傳遞數(shù)據(jù)。
Props的作用
- 傳參:Props 允許父組件向子組件傳遞數(shù)據(jù)。
- 類(lèi)型檢查:Vue 允許在定義 Props 時(shí)指定數(shù)據(jù)的類(lèi)型,這有助于在開(kāi)發(fā)過(guò)程中進(jìn)行類(lèi)型檢查,提前發(fā)現(xiàn)潛在的類(lèi)型錯(cuò)誤。
- 設(shè)置默認(rèn)值:可以為 Props 設(shè)置默認(rèn)值。當(dāng)父組件沒(méi)有傳遞該 Prop 時(shí),子組件會(huì)使用默認(rèn)值進(jìn)行渲染。
Vue 中的 Props 遵循單向數(shù)據(jù)流原則,即父組件向子組件傳遞數(shù)據(jù),子組件不能直接修改父組件傳遞過(guò)來(lái)的 Prop。
父組件傳值給子組件
在父組件的模板中,可以使用屬性綁定的方式將數(shù)據(jù)傳遞給子組件(靜態(tài)傳值):
<ChildComponent title="哈嘿" />
可以使用變量或表達(dá)式來(lái)動(dòng)態(tài)地傳遞 Props:
<!-- 根據(jù)一個(gè)變量的值動(dòng)態(tài)傳入 --> <ChildComponent :title="title" /> <!-- 根據(jù)一個(gè)更復(fù)雜表達(dá)式的值動(dòng)態(tài)傳入 --> <ChildComponent :title="someCondition ? titleA : titleB" />
可以使用 v-bind
動(dòng)態(tài)綁定所有的 props:
可以將一個(gè)對(duì)象傳遞給 v-bind
,這個(gè)對(duì)象的屬性將被用作組件的 props。
<template> <ChildComponent v-bind="obj" /> </template> <script setup lang="ts"> import ChildComponent from './ChildComponent.vue'; import { reactive } from 'vue' let obj = reactive({ message: 'Hello', count: 5 }) </script>
<ChildComponent v-bind="obj" />
等價(jià)于:
<ChildComponent :message="message" :count="count" />
聲明 Props
- 使用
defineProps
函數(shù):- 在
<script setup>
語(yǔ)法中,可以直接使用defineProps
函數(shù)來(lái)聲明組件接收的 Props。 - 在 Vue 3 中,基于類(lèi)型的聲明通常用于組合式 API 。
- 在
<script setup lang="ts"> import { defineProps } from 'vue'; // 字符串?dāng)?shù)組形式 const props = defineProps(['message', 'count']); </script>
在這個(gè)例子中,聲明了兩個(gè) Props:message
和count
。
可以使用對(duì)象字面量的方式來(lái)聲明 Props:
<script setup lang="ts"> import { defineProps } from 'vue'; const props = defineProps({ message: String, count: Number, }); </script>
在這個(gè)例子中,聲明了兩個(gè) Props:message
是字符串類(lèi)型,count
是數(shù)字類(lèi)型。通過(guò)類(lèi)型注解,TypeScript 可以在開(kāi)發(fā)過(guò)程中進(jìn)行類(lèi)型檢查,確保傳入的 props 值符合預(yù)期的類(lèi)型。
在 <script setup>
語(yǔ)法中,使用 defineProps
函數(shù)結(jié)合類(lèi)型注解來(lái)進(jìn)行基于類(lèi)型的聲明。
如果項(xiàng)目沒(méi)有使用 TypeScript,就無(wú)法使用基于類(lèi)型的聲明進(jìn)行聲明。
基于類(lèi)型的聲明可以在開(kāi)發(fā)過(guò)程中利用 TypeScript 的類(lèi)型檢查機(jī)制,提前發(fā)現(xiàn)類(lèi)型錯(cuò)誤。
- 在選項(xiàng)式 API 中(沒(méi)有使用
<script setup>
語(yǔ)法糖),props 是通過(guò)props
選項(xiàng)進(jìn)行聲明的。- 必須要用
props
選項(xiàng)聲明組件接收的Props,在setup()
的props
參數(shù)里,才有Props數(shù)據(jù)。 - 在 Vue 3 中,運(yùn)行時(shí)聲明通常用于選項(xiàng)式 API。
- 必須要用
export default { props: ['message'], setup(props) { // setup() 接收 props 作為第一個(gè)參數(shù) console.log(props.message) } }
必須要用props
選項(xiàng)聲明組件接收的Props。如果沒(méi)有 props: ['message']
:
export default { setup(props) { // 報(bào)錯(cuò): 類(lèi)型“LooseRequired<{} & {}>”上不存在屬性“message”。 console.log(props.message) } }
通過(guò)在組件選項(xiàng)對(duì)象中直接定義 props
屬性來(lái)進(jìn)行運(yùn)行時(shí)聲明:
export default { props: { message: String, count: Number, }, setup() {} // 組件的其他選項(xiàng)和邏輯 };
在這個(gè)例子中,message
被聲明為字符串類(lèi)型的 Prop,count
被聲明為數(shù)字類(lèi)型的 Prop。這種方式在運(yùn)行時(shí),Vue 會(huì)根據(jù)聲明的類(lèi)型對(duì)傳入的 Props 進(jìn)行驗(yàn)證。
運(yùn)行時(shí)聲明通常在不需要進(jìn)行嚴(yán)格類(lèi)型檢查或者需要更靈活地處理 Props 的情況下使用。它主要依賴(lài)于 Vue 的運(yùn)行時(shí)機(jī)制來(lái)處理 Props 的傳遞和驗(yàn)證。
傳遞給 defineProps()
的參數(shù)和提供給 props
選項(xiàng)的值是相同的,本質(zhì)上都是在使用 prop
選項(xiàng)。
Props 的驗(yàn)證
Props 驗(yàn)證的主要目的是確保組件接收到的數(shù)據(jù)符合預(yù)期的格式和類(lèi)型。
類(lèi)型驗(yàn)證
- 可以指定 Props 的類(lèi)型,如
String
、Number
、Boolean
、Array
、Object
等。 - 也可以是函數(shù)類(lèi)型
Function
、自定義類(lèi)型。
<script setup lang="ts"> import { defineProps } from 'vue'; // 定義一個(gè)接口作為自定義類(lèi)型 interface MyCustomType{ property1: string; property2: number; } const props = defineProps({ name: String, age: Number, hobbies: Array, address: Object, customType: MyCustomType, // 自定義類(lèi)型 onButtonClick: Function // 函數(shù)類(lèi)型 }); </script>
確保父組件傳遞給子組件的Props值與聲明的類(lèi)型一致,避免類(lèi)型錯(cuò)誤。
必需性
- 可以指定 Props 是否為必需,如果為必需,則必須在父組件中傳入。
<script setup lang="ts"> import { defineProps } from 'vue'; const props = defineProps({ message: { type: String, required: true } }); </script>
在這個(gè)例子中,message
是必需的 Prop,如果父組件沒(méi)有傳遞 message
,則會(huì)拋出警告。
自定義驗(yàn)證
- 可以使用 validator 函數(shù)進(jìn)行自定義驗(yàn)證。
<script setup lang="ts"> import { defineProps } from "vue"; let props = defineProps({ b: { type: Number, validator: (value: number) => { return value >= 0; // 自定義驗(yàn)證,確保寬度非負(fù) } } }) console.log(props) </script>
在這個(gè)例子中,b
使用了自定義驗(yàn)證函數(shù),確保b
的值不為負(fù)數(shù)。
在父組件傳入b = -10
,瀏覽器控制臺(tái)輸出警告:
默認(rèn)值
可以為 Props 設(shè)置默認(rèn)值,當(dāng)父組件沒(méi)有傳遞該 Prop 時(shí),子組件會(huì)使用默認(rèn)值進(jìn)行渲染。
<script setup lang="ts"> import { defineProps } from 'vue'; const props = defineProps({ message: { type: String, default: 'Hello, Vue 3!', }, count: { type: Number, default: 0, }, }); </script>
在這個(gè)例子中,message
的默認(rèn)值為 'Hello, Vue 3!'
,count
的默認(rèn)值為 0
。
withDefaults
在 Vue 3 中,withDefaults
是一個(gè)用于為 defineProps
定義的 props 設(shè)置默認(rèn)值的函數(shù)。
withDefaults
參數(shù)說(shuō)明:
withDefaults
的第一個(gè)參數(shù)是defineProps
的返回值,它表示組件接收的 props 對(duì)象。- 第二個(gè)參數(shù)是一個(gè)對(duì)象,其中的鍵對(duì)應(yīng)于 props 的名稱(chēng),值是相應(yīng)的默認(rèn)值。
- 默認(rèn)值是通過(guò)函數(shù)返回的。
假設(shè)有一個(gè)組件,定義了一些 props,并且希望為其中一些 props 設(shè)置默認(rèn)值:
<template> <div>{{ props.message }}</div> <div>{{ props.count }}</div> </template> <script setup lang="ts"> import { defineProps, withDefaults } from 'vue'; // 定義了一個(gè)接口 PropsInter 來(lái)描述組件的 props 結(jié)構(gòu) interface PropsInter { message: string; count: number; obj: { a: number; b: number; }; arr: string[]; } const props = withDefaults(defineProps<PropsInter>(), { message: 'Hello, Vue 3!', count: 0, obj: () => { return { a: 10, b: 5 } }, arr: () => return [ 'item1', 'item2' ] }); </script>
Boolean 類(lèi)型轉(zhuǎn)換
當(dāng)聲明為 Boolean
類(lèi)型的 props
時(shí),有特別的類(lèi)型轉(zhuǎn)換規(guī)則,以便更貼近原生的 boolean attributes 的行為。
- 當(dāng)一個(gè) prop 明確被聲明為布爾類(lèi)型時(shí),真值會(huì)被轉(zhuǎn)換為
true
,假值會(huì)被轉(zhuǎn)換為false
:- 當(dāng)父組件傳遞一個(gè)真值(如
true
、字符串"true"
、數(shù)字1
等)時(shí),該 prop 將被轉(zhuǎn)換為true
。 - 當(dāng)父組件傳遞一個(gè)假值(如
false
、字符串"false"
、數(shù)字0
、空字符串""
、null
、undefined
等)時(shí),該 prop 將被轉(zhuǎn)換為false
。
- 當(dāng)父組件傳遞一個(gè)真值(如
在子組件中:
defineProps({ disabled: Boolean })
在父組件中:
<!-- 等同于傳入 :disabled="true" --> <MyComponent disabled /> <!-- 等同于傳入 :disabled="false" --> <MyComponent />
- 當(dāng)一個(gè) prop 被聲明為允許多種類(lèi)型時(shí),聲明順序會(huì)影響 Boolean 轉(zhuǎn)換規(guī)則是否適用:
- 當(dāng)同時(shí)允許字符串和布爾類(lèi)型時(shí),如果布爾類(lèi)型出現(xiàn)在字符串類(lèi)型之前,Boolean 轉(zhuǎn)換規(guī)則才適用。
const props = defineProps({ myProp: [Boolean, String], });
如果父組件傳遞 "true"
,這個(gè)值將被轉(zhuǎn)換為布爾值 true
。如果傳遞 "false"
,將被轉(zhuǎn)換為布爾值 false
。其他字符串值將保持為字符串。
但是,如果聲明順序是 [String, Boolean]
,那么 "true"
和 "false"
將被視為字符串,而不會(huì)進(jìn)行布爾類(lèi)型的轉(zhuǎn)換。
這種邊緣情況可能會(huì)導(dǎo)致在不同的聲明順序下,相同的輸入值被解釋為不同的類(lèi)型。
使用 Props
在父組件的模板中傳值給子組件:
<ChildComponent title="哈嘿" />
在子組件的模板中,可以直接使用定義的 Props:
<template> <div>{{ title }}</div> </template> <script setup lang="ts" name="ChildComponent"> import { defineProps } from "vue"; defineProps(['title']) // console.log(title) // 報(bào)錯(cuò):找不到名稱(chēng)“title”。 </script>
在模板中,可以直接使用title
。
console.log(title)
報(bào)錯(cuò):找不到名稱(chēng)“title”。
這是因?yàn)?code>title 并沒(méi)有被直接聲明為一個(gè)可用的變量。
在 Vue 3 的 <script setup>
中,defineProps
的返回值是一個(gè)包含傳入的 props 的對(duì)象。
如果想要在組件中使用 title
,需要通過(guò)defineProps
的返回值來(lái)讀取:
<template> <div>{{ props.title }}</div> </template> <script setup lang="ts" name="ChildComponent"> import { defineProps } from "vue"; // 只接收title屬性 let props = defineProps(['title']) console.log(props) if(props.title) { console.log(props.title) } </script>
defineProps
返回一個(gè)對(duì)象 props
,props
對(duì)象中包含了 title
屬性,可以通過(guò) props.title
的方式來(lái)訪問(wèn)和使用這個(gè) prop 的值。
defineProps
的返回值是一個(gè)包含組件接收的 props
的只讀對(duì)象:
- 返回的
props
對(duì)象是只讀的。 - 返回的
props
對(duì)象包含了組件所有接收的東西:父組件傳遞給當(dāng)前組件的所有被組件明確聲明為 props 的屬性。- 必須在
defineProps
中顯式的接收父組件傳遞的屬性。假如父組件傳了幾個(gè)屬性,比如<ChildComponent title="哈嘿" id="id12345" />
,子組件defineProps(['title'])
只接收title
屬性,不會(huì)接收id
屬性。
- 必須在
- 在組件內(nèi)部不能直接修改
props
對(duì)象的屬性值。
實(shí)戰(zhàn)演練
在types/index.ts
定義一個(gè)PersonInter
接口:
// 定義一個(gè)接口,用于限制對(duì)象的具體屬性 // 接口在 TypeScript 中用于定義一種契約,確保實(shí)現(xiàn)該接口的對(duì)象都具有相同的結(jié)構(gòu)。 export interface PersonInter { id: string; name: string; age: number; }
在父組件有一個(gè)person
傳遞給子組件:
<template> <div> <ChildComponent :personList="personList" /> </div> </template> <script setup lang="ts" name="Person"> // 在 TypeScript 中,import type 語(yǔ)法用于僅導(dǎo)入類(lèi)型信息而不導(dǎo)入實(shí)際的值或函數(shù)。 // 使用 import type 導(dǎo)入的類(lèi)型信息僅在類(lèi)型檢查時(shí)使用,不會(huì)在運(yùn)行時(shí)產(chǎn)生任何影響。 import type { PersonInter } from '@/types'; import { reactive } from 'vue'; import ChildComponent from './ChildComponent.vue'; let personList = reactive<PersonInter>({ id: 'person001', name: 'John', age: 18 }); </script>
子組件:
<template> <div>{{ person.name }}</div> </template> <script setup lang="ts" name="ChildComponent"> import type { PersonInter } from '@/types'; import { defineProps } from "vue"; // 只接收person let props = defineProps(['person']) console.log(props) // 接收person+類(lèi)型限制 let props = defineProps<{ person: PersonInter }>() // 接收person+類(lèi)型限制+限制必要性+默認(rèn)值 // ?表示不必傳,父組件可傳可不傳,如果父組件不傳,則使用默認(rèn)值 // 指定默認(rèn)值需要使用withDefaults withDefaults(defineProps<{ person?: PersonInter }>(), { person: () => { return { id: 'person000', name: 'Alice', age: 18 } } }) </script>
let props = defineProps(['person'])
只接收person
,對(duì)person
沒(méi)有任何限制。父組件可以給person
賦任意類(lèi)型的值。defineProps<{ person: PersonInter }>()
: 通過(guò)泛型參數(shù)指定了props
的結(jié)構(gòu)。具體來(lái)說(shuō),定義了一個(gè)名為person
的 prop,其類(lèi)型為PersonInter
。defineProps<{ person?: PersonInter }>()
:- 使用泛型參數(shù)指定了
props
的結(jié)構(gòu)。定義了一個(gè)名為person
的 prop,其類(lèi)型為PersonInter
。 - 后面的問(wèn)號(hào)
?
表示這個(gè) prop 是可選的,即父組件可以選擇是否傳遞這個(gè) prop。
- 使用泛型參數(shù)指定了
總結(jié)
到此這篇關(guān)于vue3 Props用法(父?jìng)髯?的文章就介紹到這了,更多相關(guān)vue3 Props用法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue項(xiàng)目遇見(jiàn)事件冒泡該如何處理詳解
冒泡事件處理是由內(nèi)而外發(fā)生的,例如有兩個(gè)父子div,給他們分別寫(xiě)上點(diǎn)擊事件,點(diǎn)擊子div先響應(yīng)的是子div,再是父div,下面這篇文章主要給大家介紹了關(guān)于vue項(xiàng)目遇見(jiàn)事件冒泡該如何處理的相關(guān)資料,需要的朋友可以參考下2023-04-04Ant-design-vue Table組件customRow屬性的使用說(shuō)明
這篇文章主要介紹了Ant-design-vue Table組件customRow屬性的使用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10Vue中對(duì)iframe實(shí)現(xiàn)keep alive無(wú)刷新的方法
這篇文章主要介紹了Vue中對(duì)iframe實(shí)現(xiàn)keep alive無(wú)刷新的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07vue :style設(shè)置背景圖片方式backgroundImage
這篇文章主要介紹了vue :style設(shè)置背景圖片方式backgroundImage,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10詳解auto-vue-file:一個(gè)自動(dòng)創(chuàng)建vue組件的包
這篇文章主要介紹了auto-vue-file:一個(gè)自動(dòng)創(chuàng)建vue組件的包,需要的朋友可以參考下2019-04-04react+?ts?vite搭建及二次封裝請(qǐng)求的過(guò)程解析
這篇文章主要介紹了react+?ts?vite搭建及二次封裝請(qǐng)求,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04