本篇把Vue Nuxt 3頁面中的下拉選單改用code mapping的方式改寫。
原本訂單例表的出口國家是顯示代碼,但通常需要轉成較易讀的文字,例如US代表美國,這種代碼與文字的轉換就叫code mapping。
事前要求
參考「Vue Nuxt 3 useFetch 多查詢參數」中的下拉選單。
修改pages/home/export/index.vue
原本的下拉選單值和文字是寫死的,這邊抽出來為物件countryMap,然後在下拉選單的<option>用Vue的v-for迴圈渲染物件。
v-for="(name, code) in countryMap"語法中的name為value(例如"美國"),code為key(例如"US")。
在查詢出來訂單資料中使用{{ countryMap[order.country] }}來顯示對應的國家名稱。
pages/home/export/index.vue
<template>
<div>
<h1>出口業務</h1>
<label>
訂單狀態:
<input v-model="status" placeholder="pending/done">
</label>
<br>
<label>
出口國家:
<select v-model="country">
<option value="">全部國家</option>
<option v-for="(name, code) in countryMap" :key="code" :value="code">
{{ name }} ({{ code }})
</option>
</select>
</label>
<br>
<button @click="search">查詢</button>
<!--省略-->
<ul v-else>
<li v-for="order in orders" :key="order.id">
<NuxtLink :to="`/home/export/${order.id}`">
訂單 #{{ order.id }}, 狀態: {{ order.status }},
出口國家:{{ countryMap[order.country] }}
</NuxtLink>
</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
const countryMap = {
US: '美國',
JP: '日本',
CN: '中國',
KR: '韓國',
VN: '越南'
}
// 省略
</script>
<!--省略-->
選單資料移到後端API
通常代碼類的下拉選單很多地方都會用到,所以接著把countryMap的內容搬到後端API [GET] /api/countries統一取得國家代碼。
新增server/api/countries.get.js來模擬/api/countries。
server/api/countries.get.js
export default defineEventHandler(async () => {
await new Promise((r) => setTimeout(r, 1000)); // 模擬延遲
const countryMap = {
US: "美國",
JP: "日本",
CN: "中國",
KR: "韓國",
VN: "越南",
};
return countryMap;
});
則原本頁面的countryMap改由後端API/api/countries取得。當畫面同時有多個API(例如現在有訂單和國家代碼)時,可以各自設計loading和error效果,例如countryPending和orderPending。
pages/home/export/index.vue
<template>
<div>
<h1>出口業務</h1>
<label>
訂單狀態:
<input v-model="status" placeholder="pending/done">
</label>
<br>
<label>
出口國家:
<select v-model="country" :disabled="countryPending">
<option value="">全部國家</option>
<option v-for="(name, code) in countryMap" :key="code" :value="code">
{{ name }} ({{ code }})
</option>
</select>
</label>
<br>
<button @click="search">查詢</button>
<p v-if="orderPending">資料載入中...</p>
<p v-else-if="error" class="error">資料載入失敗</p>
<p v-else-if="orders.length === 0">沒有訂單資料</p>
<ul v-else>
<li v-for="order in orders" :key="order.id">
<NuxtLink :to="`/home/export/${order.id}`">
訂單 #{{ order.id }},
狀態: {{ order.status }},
出口國家:{{ countryMap[order.country] }}
</NuxtLink>
</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
const route = useRoute()
const router = useRouter()
const status = ref(route.query.status || '')
const queryStatus = ref(route.query.status || '')
const country = ref(route.query.country || '')
const queryCountry = ref(route.query.country || '')
const { data: orders, pending: orderPending, error, refresh } = useFetch('/api/orders', {
query: {
status: queryStatus,
country: queryCountry,
},
default: () => [],
})
const { data: countryMap, pending: countryPending } = useFetch('/api/countries', {
default: () => ({}), // default的型別要和API回傳的資料結構一致
})
// ...
</script>
<!-- ... -->
效果如下:
沒有留言:
張貼留言