Vue 泛型元件,讓 TypeScript 更精確

鱈魚-avatar-img
發佈於Vue
更新 發佈閱讀 8 分鐘
鱈魚的魚缸搬家了!新家文章皆有重新修訂,歡迎來新家看看喔。(´▽`ʃ♡ƪ)



大家好,我是鱈魚。(^∀^●)ノシ


Vue 3.3 終於新增了泛型元件(Generic Component),這讓我們可以在 TypeScript 環境中得到更準確的型別提示。ˋ( ° ▽、° )


這個泛型元件與 TypeScript 的 Generic 是同一個概念,不知道 Generic 的朋友可以先來來複習一下


甚麼?你說你沒有使用 TypeScript?抱歉浪費您 5 秒鐘,可以上一頁了。(>人<;)


或者在離開前路過文檔湊個熱鬧。(. ❛ ᴗ ❛.)


有使用 TypeScript 的朋友就讓我們一起繼續看下去吧。ლ(╹◡╹ლ)

來個 select

假設我需要一個綁定物件的 select,最常見的問題就是 modelValue 只能 any,如下:

SelectAny.vue

<script setup lang="ts">
...(省略其他程式碼)

interface Prop {
modelValue: any;
label?: string;
options: any[];
optionLabel?: (option: any) => string;
/** 是否多選 */
multiple?: boolean;
}

...
</script>
...

v-model 這個糖

忘記元件怎麼實現 v-model 的朋友們別擔心,讓我們複習一下。


💡 Vue 3.4 開始可以使用 defineModel,不過與此文主題無關,所以我們先使用經典寫法。


v-model 只是一個語法糖,實際上的程式碼如下(文檔)。

<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script>

<template>
<input
:value="props.modelValue"
@input="emit('update:modelValue', $event.target.value)"
/>
</template>

modelValue 就是用來表示預設綁定值的變數,讓我們回到剛剛的 any。


所以現在就算我們的 modelValue 與 options 的型別不同,或者 multiple 為 true,而 modelValue 卻沒有給矩陣時,都不會有任何錯誤提示。

<script setup lang="ts">
...
import SelectAny from './SelectAny.vue';

const options: User[] = [
{ name: '鱈魚', price: 10000 },
{ name: '章魚', price: 100 }
];

const anyDatum = ref<{ age: number }>();
const seletedAnyDatum = ref<User>();
</script>

<template>
<!-- anyDatum 與 option 型別不同 -->
<SelectAny v-model="anyDatum" :options="options" :option-label="getLabel" />

<!-- modelValue 沒有給矩陣 -->
<SelectAny v-model="seletedAnyDatum" multiple :options="options" :option-label="getLabel" />
</template>

畢竟是 any 嘛。(˘・_・˘)


加上泛型

如果加上元件泛型就不會有以上問題了。

SelectGeneric.vue

<script 
setup
lang="ts"
generic="ModelValue, Multiple extends boolean"
>
...

interface Prop {
modelValue: Multiple extends true ? ModelValue[] : ModelValue;
label?: string;
options: ModelValue[];
optionLabel?: (option: any) => string;
/** 是否多選 */
multiple?: Multiple;
}

...
</script>
...

除了 modelValue、options 有泛型 ModelValue 外,我們還加上 multiple 判斷,如果為 true,則 modelValue 為 ModelValue[],否則為 ModelValue。


這樣子就可以達成以下效果:

  • modelValue 與 options 型別不同時警告,
  • multiple 為 true 時,如果 modelValue 沒有提供矩陣時發出警告。
<script setup lang="ts">
...
import SelectGeneric from './SelectGeneric.vue';

const options: User[] = [
{ name: '鱈魚', price: 10000 },
{ name: '章魚', price: 100 }
];

const anyDatum = ref<{ age: number }>();
const seletedGenericDatum = ref<User>();
const seletedGenericData = ref<User[]>([]);
</script>

<template>
<!-- Type '{ age: number; }' is not assignable to type 'User | User[]'.ts(2322) -->
<SelectGeneric v-model="anyDatum" :options="options" :option-label="getLabel" />

<!-- Type 'User' is not assignable to type 'User[]'.ts(2322) -->
<SelectGeneric v-model="seletedGenericDatum" multiple :options="options" :option-label="getLabel" />

<!-- 正確 -->
<SelectGeneric v-model="seletedGenericData" multiple :options="options" :option-label="getLabel" />
</template>

TypeScript 成功重返光榮。o((>ω< ))o


文章到此結束了,感謝您的閱讀,以上程式碼可以在此取得。

有其他想法請不吝告訴我,鱈魚感謝您!(o゜▽゜)o☆

留言
avatar-img
鱈魚的魚缸
17會員
14內容數
各種鱈魚滾鍵盤的雜紀
鱈魚的魚缸的其他內容
2024/07/25
先前提到 Quasar 的 Dialog Plugin 很好用,再讓我補充一個用法。
Thumbnail
2024/07/25
先前提到 Quasar 的 Dialog Plugin 很好用,再讓我補充一個用法。
Thumbnail
2024/07/15
Quasar Dialog 的 Invoking custom component 很好用,但是有些困擾的地方,一起來看看有甚麼辦法吧。
Thumbnail
2024/07/15
Quasar Dialog 的 Invoking custom component 很好用,但是有些困擾的地方,一起來看看有甚麼辦法吧。
Thumbnail
2024/07/10
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
Thumbnail
2024/07/10
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
Thumbnail
看更多
你可能也想看
Thumbnail
本章節旨在介紹 TypeScript 的基本資料型別,包括內建型別、型別轉換、自訂型別、元組、集合、陣列、和字典型別。透過理解和使用這些型別,可以提高代碼的可讀性和可維護性。
Thumbnail
本章節旨在介紹 TypeScript 的基本資料型別,包括內建型別、型別轉換、自訂型別、元組、集合、陣列、和字典型別。透過理解和使用這些型別,可以提高代碼的可讀性和可維護性。
Thumbnail
上一篇文章分享了 TypeScript 的定義、前端角色定位,如果你不是很確定「TypeScript 是什麼?」、「TypeScript 作為 JavaScript 的超集,在網頁開發扮演怎麼樣的角色?」這兩個問題的答案,建議可以回到上一篇先了解一下。
Thumbnail
上一篇文章分享了 TypeScript 的定義、前端角色定位,如果你不是很確定「TypeScript 是什麼?」、「TypeScript 作為 JavaScript 的超集,在網頁開發扮演怎麼樣的角色?」這兩個問題的答案,建議可以回到上一篇先了解一下。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
《轉轉生》(Re:INCARNATION)為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,結合拉各斯街頭節奏、Afrobeat/Afrobeats、以及約魯巴宇宙觀的非線性時間,建構出關於輪迴的「誕生—死亡—重生」儀式結構。本文將從約魯巴哲學概念出發,解析其去殖民的身體政治。
Thumbnail
《轉轉生》(Re:INCARNATION)為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,結合拉各斯街頭節奏、Afrobeat/Afrobeats、以及約魯巴宇宙觀的非線性時間,建構出關於輪迴的「誕生—死亡—重生」儀式結構。本文將從約魯巴哲學概念出發,解析其去殖民的身體政治。
Thumbnail
在 Vue 專案中使用 Apollo Graphql Client 從 API 獲取資料,由於資料結構較為複雜,筆者便跟著網路教學使用 codegen 工具自動化產生 TypeScript 型別定義。在某個元件中,需要使用 defineProps 來撰寫型別定義,結果⋯⋯
Thumbnail
在 Vue 專案中使用 Apollo Graphql Client 從 API 獲取資料,由於資料結構較為複雜,筆者便跟著網路教學使用 codegen 工具自動化產生 TypeScript 型別定義。在某個元件中,需要使用 defineProps 來撰寫型別定義,結果⋯⋯
Thumbnail
Vue3 學習筆記,專案建立與基礎響應式篇
Thumbnail
Vue3 學習筆記,專案建立與基礎響應式篇
Thumbnail
大家好,我是鱈魚。(^∀^●)ノシ Vue 3.3 終於新增了泛型元件(Generic Component),這讓我們可以在 TypeScript 環境中得到更準確的型別提示。( •̀ ω •́ )✧ 讓我們一起來看看吧!
Thumbnail
大家好,我是鱈魚。(^∀^●)ノシ Vue 3.3 終於新增了泛型元件(Generic Component),這讓我們可以在 TypeScript 環境中得到更準確的型別提示。( •̀ ω •́ )✧ 讓我們一起來看看吧!
Thumbnail
在AI浪潮下,009819 中信美國數據中心及電力ETF 直接卡位算力與電力雙主軸,等於掌握AI最核心基建。2008從 Apple Inc. 與 iPhone 帶動供應鏈,到如今AI崛起,主線已由應用端轉向底層。AI發展離不開算力與電力支撐,009819的價值,在於押中「沒有它不行」的核心資產。
Thumbnail
在AI浪潮下,009819 中信美國數據中心及電力ETF 直接卡位算力與電力雙主軸,等於掌握AI最核心基建。2008從 Apple Inc. 與 iPhone 帶動供應鏈,到如今AI崛起,主線已由應用端轉向底層。AI發展離不開算力與電力支撐,009819的價值,在於押中「沒有它不行」的核心資產。
Thumbnail
Vue3 筆記,指令進階篇
Thumbnail
Vue3 筆記,指令進階篇
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News