Vue3使用withDefaults和defineProps設(shè)置默認(rèn)值的操作指南
直接在defineProps中設(shè)置默認(rèn)值
優(yōu)點(diǎn):
- 對于簡單的組件,在
defineProps對象中直接設(shè)置默認(rèn)值是一種簡潔的方式。所有props的定義,包括類型和默認(rèn)值,都集中在一個地方,一目了然。可以很方便地看到每個props的類型和默認(rèn)值信息。例如:
<script setup>
const props = defineProps({
count: {type: Number,default: 0},
name: {type: String,default: 'Guest'}
});
</script>
- 當(dāng)
props是一個復(fù)雜的對象類型,并且默認(rèn)值是一個對象時,直接在defineProps中設(shè)置默認(rèn)值可以更好地利用對象的解構(gòu)特性。例如:
<script setup>
const props = defineProps({
user: {type: Object,default: () => ({name: 'Guest',age: 18})}
});
</script>
這里可以直接返回一個函數(shù)來生成默認(rèn)的對象值,在組件初始化時會根據(jù)這個函數(shù)生成默認(rèn)的user對象。
缺點(diǎn):
- 當(dāng)
props的定義比較復(fù)雜,或者需要對默認(rèn)值進(jìn)行一些復(fù)雜的計(jì)算或處理時,會使defineProps中的代碼變得臃腫。例如,如果默認(rèn)值需要調(diào)用一個函數(shù)來生成,會讓props的定義看起來不夠清晰。而且如果多個組件有相似的props默認(rèn)值設(shè)置邏輯,這種方式不利于代碼的復(fù)用。 - Vue3 的
defineProps解決了部分響應(yīng)式問題(返回的是 “響應(yīng)式 Proxy 對象”),但如果直接對defineProps的結(jié)果解構(gòu),依然會丟失默認(rèn)值(響應(yīng)式可通過toRefs保留,但默認(rèn)值不行)
<!-- Vue3 組件:TestProps.vue(無withDefaults) -->
<template>
<div>
<!-- 父組件沒傳props時,期望顯示默認(rèn)值,實(shí)際顯示 undefined -->
<h1>{{ title }}</h1>
<p>計(jì)數(shù):{{ count }}</p>
</div>
</template>
<script setup lang="ts">
// 1. 定義props并設(shè)置默認(rèn)值(通過第二個參數(shù))
const props = defineProps<{
title?: string;
count?: number;
}>({
title: {
type: String,
default: "默認(rèn)標(biāo)題"
},
count: {
type: Number,
default: 100
}
});
// 2. 直接解構(gòu):丟失默認(rèn)值(響應(yīng)式可通過toRefs保留,但默認(rèn)值不行)
const { title, count } = props;
console.log(title); // undefined(而非 "默認(rèn)標(biāo)題")
console.log(count); // undefined(而非 100)
// 3. 用toRefs解構(gòu):保留響應(yīng)式,但仍丟失默認(rèn)值
import { toRefs } from "vue";
const { title: refTitle, count: refCount } = toRefs(props);
console.log(refTitle.value); // undefined(依然沒有默認(rèn)值)
</script>
可見:Vue3 中即便用了defineProps,若不配合withDefaults,Vue2 的 “解構(gòu)丟失默認(rèn)值” 問題依然存在 —— 這正是withDefaults要解決的核心場景之一。
使用withDefaults設(shè)置默認(rèn)值
優(yōu)點(diǎn):
withDefaults將默認(rèn)值的設(shè)置與props的類型定義分離開來,使得代碼結(jié)構(gòu)更加清晰。特別是當(dāng)props的類型定義比較復(fù)雜,或者有多個props需要設(shè)置默認(rèn)值時,這種分離可以提高代碼的可讀性。例如:
<script setup>
import { withDefaults } from 'vue';
const props = defineProps({count: Number,name: String});
withDefaults(props, {count: 0,name: 'Guest'});
</script>
- 先專注于
props的類型定義,然后在另一個地方(withDefaults調(diào)用處)清晰地設(shè)置默認(rèn)值。如果需要在多個組件中復(fù)用默認(rèn)值設(shè)置邏輯,可以將withDefaults的調(diào)用封裝成一個函數(shù)。 withDefaults在處理復(fù)雜對象類型的默認(rèn)值時,與直接在defineProps中設(shè)置默認(rèn)值的功能類似,但語法上略有不同。
<script setup>
import { withDefaults } from 'vue';
const props = defineProps({user: Object});
withDefaults(props, {user: () => ({name: 'Guest',age: 18})});
</script>
同樣是通過一個函數(shù)來生成默認(rèn)的對象值,但需要注意的是,withDefaults在處理默認(rèn)值時,對于引用類型(如對象、數(shù)組)的數(shù)據(jù),如果默認(rèn)值是一個引用類型的字面量(如{}或[]),這個引用在所有組件實(shí)例中是共享的。這可能會導(dǎo)致一些意外的行為,例如一個組件修改了默認(rèn)值對象的屬性,可能會影響到其他組件的默認(rèn)值。所以在使用withDefaults設(shè)置引用類型的默認(rèn)值時,通常建議像上面那樣返回一個新的對象或數(shù)組。
withDefaults解構(gòu)后仍能讀取到默認(rèn)值
withDefaults是 Vue3 為defineProps設(shè)計(jì)的 “默認(rèn)值增強(qiáng)工具”,它的核心作用有兩個:
- 讓
defineProps的默認(rèn)值與 TypeScript 類型緊密綁定(類型安全); - 確保解構(gòu)后仍能讀取到默認(rèn)值(徹底解決 Vue2 遺留的痛點(diǎn))。
<!-- Vue3 組件:TestProps.vue(用withDefaults) -->
<template>
<div>
<!-- 父組件沒傳props時,正確顯示默認(rèn)值 -->
<h1>{{ title }}</h1> <!-- "默認(rèn)標(biāo)題" -->
<p>計(jì)數(shù):{{ count }}</p> <!-- 100 -->
</div>
</template>
<script setup lang="ts">
// 1. 用withDefaults定義props:默認(rèn)值與類型綁定
const props = withDefaults(defineProps<{
title?: string; // 可選類型,配合默認(rèn)值
count?: number; // 可選類型,配合默認(rèn)值
}>(), {
// 定義默認(rèn)值(會自動校驗(yàn)類型,不符合TS類型會報錯)
title: "默認(rèn)標(biāo)題",
count: () => 100, // 復(fù)雜類型(如對象/數(shù)組)需用函數(shù)返回(避免復(fù)用問題)
});
// 2. 直接解構(gòu):默認(rèn)值生效,且響應(yīng)式保留(因?yàn)閣ithDefaults處理過)
const { title, count } = props;
console.log(title); // "默認(rèn)標(biāo)題"(正確讀取默認(rèn)值)
console.log(count); // 100(正確讀取默認(rèn)值)
// 3. 父組件傳值時,會覆蓋默認(rèn)值(符合預(yù)期)
// 若父組件調(diào)用:<TestProps title="新標(biāo)題" count={200} />
// 此時解構(gòu)后 title = "新標(biāo)題",count = 200
</script>
withDefaults 為什么能解決問題?
withDefaults本質(zhì)是對defineProps返回的 “響應(yīng)式 props 對象” 做了一層 “增強(qiáng)代理”:
- 當(dāng)訪問
props.title時,若父組件沒傳值,代理會自動返回withDefaults中定義的默認(rèn)值; - 即便解構(gòu)(
const { title } = props),拿到的依然是 “帶默認(rèn)值邏輯的響應(yīng)式引用”(而非原始值),所以默認(rèn)值不會丟失; - 同時,
withDefaults會強(qiáng)制默認(rèn)值的類型與defineProps的 TS 類型一致(比如給title傳123,TS 會直接報錯),比 Vue2 的type校驗(yàn)更嚴(yán)格。
缺點(diǎn):
代碼的位置相對分散,需要查看兩個地方(
defineProps和withDefaults)才能完整地了解props的定義和默認(rèn)值情況。對于簡單的props設(shè)置,可能會覺得有些繁瑣。
withDefaults的使用場景
提高代碼可讀性和組織性
(1)復(fù)雜組件的**props**默認(rèn)值設(shè)置
當(dāng)組件具有多個props,并且每個props都需要設(shè)置默認(rèn)值時,使用withDefaults可以讓代碼結(jié)構(gòu)更清晰。
這樣,props的類型定義和默認(rèn)值設(shè)置分開,便于開發(fā)者閱讀和理解。先看到props的類型定義,能快速了解組件接受哪些類型的屬性,然后通過withDefaults看到默認(rèn)值的設(shè)置,使得代碼邏輯更加清晰,尤其在大型項(xiàng)目或者復(fù)雜組件開發(fā)中,有助于提高代碼的可維護(hù)性。
(2)遵循組件開發(fā)規(guī)范和團(tuán)隊(duì)協(xié)作要求 在團(tuán)隊(duì)開發(fā)中,可能會有代碼風(fēng)格和組件開發(fā)規(guī)范的要求。使用withDefaults可以更好地符合這些規(guī)范。例如,規(guī)定props的類型定義和默認(rèn)值設(shè)置分開,這樣在代碼審查或者新成員加入團(tuán)隊(duì)時,能夠更容易理解組件的props邏輯。而且,這種規(guī)范的代碼結(jié)構(gòu)有助于提高代碼的復(fù)用性,方便在其他組件中復(fù)用props的定義和默認(rèn)值設(shè)置邏輯。
便于默認(rèn)值的動態(tài)生成和復(fù)用
(1)動態(tài)生成默認(rèn)值
有時候props的默認(rèn)值需要根據(jù)一些外部條件或者組件內(nèi)部狀態(tài)來動態(tài)生成。使用withDefaults可以方便地實(shí)現(xiàn)這一點(diǎn)。例如,一個國際化組件,其默認(rèn)文本需要根據(jù)當(dāng)前語言環(huán)境來生成:
<script setup>
import { withDefaults, ref } from 'vue';
import i18n from './i18n';
const props = defineProps({
buttonText: String
});
const currentLanguage = ref(i18n.getCurrentLanguage());
function generateDefaultButtonText() {
return i18n.getTextForLanguage(currentLanguage.value, 'defaultButtonText');
}
withDefaults(props, {
buttonText: generateDefaultButtonText
});
</script>
這里通過一個函數(shù)generateDefaultButtonText來動態(tài)生成buttonText的默認(rèn)值,該函數(shù)可以根據(jù)當(dāng)前語言環(huán)境獲取合適的默認(rèn)文本。這種方式使得默認(rèn)值的生成更加靈活,能夠適應(yīng)不同的應(yīng)用場景。
(2)默認(rèn)值邏輯復(fù)用
如果多個組件需要相同或相似的默認(rèn)值設(shè)置邏輯,可以將withDefaults的調(diào)用封裝成一個函數(shù)。例如,有多個數(shù)據(jù)展示組件都需要對data屬性設(shè)置默認(rèn)值為空數(shù)組,對loading屬性設(shè)置默認(rèn)值為false:
function setCommonDefaults(props) {
withDefaults(props, {
data: () => [],
loading: false
});
}
然后在各個組件中使用這個函數(shù):
<script setup>
import { defineProps, withDefaults } from 'vue';
import { setCommonDefaults } from './commonDefaults';
const props = defineProps({
data: Array,
loading: Boolean
});
setCommonDefaults(props);
</script>
這樣可以提高代碼的復(fù)用性,減少重復(fù)代碼,同時也便于統(tǒng)一修改默認(rèn)值設(shè)置邏輯。
以上就是Vue3使用withDefaults和defineProps設(shè)置默認(rèn)值的操作指南的詳細(xì)內(nèi)容,更多關(guān)于Vue3 withDefaults和defineProps設(shè)置默認(rèn)值的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Template?ref在Vue3中的實(shí)現(xiàn)原理詳解
這篇文章主要為大家介紹了Template?ref在Vue3中的實(shí)現(xiàn)原理示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
詳解Vue中Computed與watch的用法與區(qū)別
這篇文章主要介紹了Vue中computed和watch的使用與區(qū)別,文中通過示例為大家進(jìn)行了詳細(xì)講解,對Vue感興趣的同學(xué),可以學(xué)習(xí)一下2022-04-04
VUEJS實(shí)戰(zhàn)之構(gòu)建基礎(chǔ)并渲染出列表(1)
這篇文章主要為大家詳細(xì)介紹了VUEJS實(shí)戰(zhàn)之構(gòu)建基礎(chǔ)并渲染出列表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-06-06

