Vue

2022.04.15

用 VUE 套件 v-select 製作關聯台灣鄉鎮市區的下拉選單


今天把這個功能做完了,最後開會討論卻要把它拿掉 XDDD….,所以就來記錄一下自己的做法,這樣以後如果還需要,就可以撿回來用啦!

其實用 VUE 實作這種下拉選單的功能,網路上能找到很多範例,所以這邊就不贅述了。

這篇文章跟其他範例的差別,在於我是有搭配 v-select 這個套件來使用,因此假設你也用了 Vue Select 套件,也想做這個功能,那希望這篇文章能幫到你!

安裝 Vue Select 套件

▼ 可以用 yarn 或 npm 套件管理安裝,有支援 vue3

# vue 2
yarn add vue-select

# vue 3
yarn add vue-select@beta

# or, using NPM
npm install vue-select

▼ 接著要註冊元件

import Vue from 'vue'
import vSelect from 'vue-select'

Vue.component('v-select', vSelect)

▼ 載入 CSS 檔案

import 'vue-select/dist/vue-select.css';

使用 Vue Select 套件

我這邊有一份 fork 自 abc873693 的台灣鄉鎮市區 JSON 檔案,存放在我的 gist 裡,我們就用這份做範例吧。

import TwCities.json 後,將資料顯示在 v-select 套件上。

import cities from '@/json/TwCities.json'

v-select 是封裝元件,沒辦法在 options 裡面放 v-for,所以直接在 v-select 上寫 :options= "cities"。json 裡面的欄位是 name ("name" : "臺北市"),我們要在 v-select 裡面將 label 設為 name,不然會找不到資料。

<v-select label="name" placeholder="縣市" :options="cities"></v-select>

▼ 接著重頭戲來囉!我們要將兩個 v-select 設為關聯,可以使用 :reduce 這個 API

官方介紹的 reduce API Props:

When working with objects, the reduce prop allows you to transform a given object to only the information you want passed to a v-model binding or @input event.

reduce: {
  type: Function,
  default: option => option,
}

▼ 利用 :reduce 將選到的資料傳入我們宣告的陣列 (citySelect) 裡

<v-select label="name" :reduce="(option) => citySelect = option.districts" placeholder="縣市" :options="cities"></v-select>
import { ref } from 'vue'
import cities from '@/json/TwCities.json'

export default {
  setup () {
    const citySelect = ref([])
    const selected = ref('')
    return { citySelect, cities }
  }
}

▼ 再讓「鄉鎮區域」的下拉選單,讀取這一包檔案,就可以建立關聯了

<v-select label="name" placeholder="鄉鎮區域" :options="citySelect"></v-select>

▼ 不過用 :reduce 時,option 預設會跑最後一筆資料,所以我一直撈到金門的縣市。因此我回頭新增了一個空物件在 json 上,然後讓他預設是空值。

<div>
  <v-select label="name" :reduce="(option) => { citySelect = option.districts; selected = option.districts[0] ? option.districts[0].name : '' ;" placeholder="縣市" :options="cities"></v-select>
</div>
<div>
  <v-select label="name" placeholder="鄉鎮區域" v-model="selected" :options="citySelect"></v-select>
</div>
import { ref } from 'vue'
import cities from '@/json/TwCities.json'

export default {
  setup () {
    const citySelect = ref([])
    const selected = ref('')
    return { citySelect, cities, selected }
  }
}

這不是一個很好的寫法,因為會動到 json 檔,但我暫時找不出該怎麼調整,所以只好先放著,回頭再來解這個 issue 吧!

範例程式

最後放上範例程式,再請各位多多指教!

歡迎給我點鼓勵,讓我知道你來過 :)

1
guest
2 則留言
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Michael0520
Michael0520
3 months ago

我先前也是使用此套件,為了不要改動到原始資料,所以深層拷貝了一份 data 來使用,不確定有沒有更好的方式,有的話再麻煩回覆摟,感謝~

Copyright (C) MUKI space* / Reborn Theme All Rights Reserved.