Cascader 级联选择 - Vant 4
Cascader 級聯選擇
🔗 介紹
想像一下,你正在網購時需要選擇收貨地址 📍,從省份到城市再到區縣,一層層地精準定位。Cascader 級聯選擇元件就像一個智慧的「地圖導航員」 🗺️,幫你在複雜的層級資料中輕鬆穿梭!
無論是省市區三級聯動、商品分類篩選,還是組織架構選擇,Cascader 都能讓原本繁瑣的多層選擇變得如絲般順滑 ✨。它就像一個貼心的嚮導,一步步引導使用者找到最終目標,讓複雜的資料結構在指尖變得簡單易懂!
📦 引入
透過以下方式來全域註冊元件,更多註冊方式請參考元件註冊。
import { createApp } from'vue';
import { Cascader } from'vant';
const app = createApp();
app.use(Cascader);🎯 程式碼演示
基礎用法
就像搭積木一樣簡單 🧱!Cascader 與 Field 和 Popup 元件完美配合,就像三個好朋友手拉手,共同打造出絲滑的選擇體驗。
點擊輸入框,彈出層級選擇面板,一層層選擇下去,最終的路徑會自動拼接成完整的選擇結果 🎯。這種體驗就像在玩一個有趣的「尋寶遊戲」,每一步都充滿期待!
import { ref } from'vue';
export default {
setup() {
const show = ref(false);
const fieldValue = ref('');
const cascaderValue = ref('');
// 选项列表,children 代表子选项,支持多级嵌套
const options = [ { text: '浙江省', value: '330000', children: [{ text: '杭州市', value: '330100' }], }, { text: '江苏省', value: '320000', children: [{ text: '南京市', value: '320100' }], }, ];
// 全部选项选择完毕后,会触发 finish 事件
const onFinish = ({ selectedOptions }) => {
show.value = false;
fieldValue.value = selectedOptions.map((option) => option.text).join('/');
};
return { show, options, onFinish, fieldValue, cascaderValue, };
}
};中國省市區資料
做電商應用最頭疼的是什麼?當然是省市區資料啦 😅!別擔心,Vant 就像一個貼心的管家,已經為你準備好了一份完整的中國省市區資料 🇨🇳。
這份資料就像一個「地理百科全書」,從黑龍江到海南,從新疆到上海,應有盡有!只需要安裝一個小小的 npm 包,就能讓你的應用瞬間擁有全國地址選擇能力 🚀:
# 通过 npm
npm i @vant/area-data
# 通过 yarn
yarn add @vant/area-data
# 通过 pnpm p
npm add @vant/area-data
# 通过 Bun
bun add @vant/area-dataimport { ref } from'vue';
import { useCascaderAreaData } from'@vant/area-data';
export default { setup() {
const show = ref(false);
const fieldValue = ref('');
const cascaderValue = ref('');
const options = useCascaderAreaData();
const onFinish = ({ selectedOptions }) => { show.value = false; fieldValue.value = selectedOptions.map((option) => option.text).join('/'); };
return { show, options, onFinish, fieldValue, cascaderValue, };
},
};Tips: 中國的行政區劃每年都會有變動,如果發現省市區資料未及時更新,歡迎提 Pull Request 幫助我們更新。你可以在「國家統計局 - 全國區劃代碼」 和「民政部 - 行政區劃代碼」上查詢到最新資料,請根據官方資料進行核實。
自訂顏色
想要讓你的級聯選擇器更有個性?🎨 active-color 屬性就像一支神奇的畫筆,可以為選中狀態塗上你喜歡的顏色!
無論是品牌藍、活力橙還是優雅紫,都能讓你的元件與眾不同,完美融入應用的整體設計風格 ✨。
非同步載入選項
有時候資料太多,一次性載入會讓使用者等得花兒都謝了 🌸。這時候非同步載入就像一個「智慧快遞員」 📦,按需配送,使用者選到哪一層,就載入哪一層的資料。
透過監聽 change 事件,你可以在使用者選擇時動態獲取下級資料,讓選擇過程既流暢又高效!
import { ref } from'vue';
import { closeToast, showLoadingToast } from'vant';
export default { setup() {
const show = ref(false);
const fieldValue = ref('');
const cascaderValue = ref('');
const options = ref([ { text: '浙江省', value: '330000', children: [], }, ]);
const onChange = ({ value }) => {
if ( value === options.value[0].value && options.value[0].children.length === 0 ) {
// 模拟数据请求
showLoadingToast('加载中...');
setTimeout(() => {
options.value[0].children = [ { text: '杭州市', value: '330100' }, { text: '宁波市', value: '330200' }, ];
closeToast(); }, 1000);
}
};
const onFinish = ({ selectedOptions }) => { show.value = false; fieldValue.value = selectedOptions.map((option) => option.text).join('/'); };
return { show, options, onFinish, fieldValue, cascaderValue, };
},
};自訂欄位名稱
每個專案都有自己的「語言習慣」 🗣️,有的喜歡用 name,有的偏愛 title,有的鍾情於 label。Cascader 就像一個「翻譯官」 🌐,透過 field-names 屬性讓你的資料結構和元件完美對接!
不管你的後端同事用什麼欄位名,Cascader 都能輕鬆適配,讓資料對接變得毫無壓力 💪。
import { ref } from'vue'; exportdefault { setup() { const code = ref(''); const fieldNames = { text: 'name', value: 'code', children: 'items', }; const options = [ { name: '浙江省', code: '330000', items: [{ name: '杭州市', code: '330100' }], }, { name: '江苏省', code: '320000', items: [{ name: '南京市', code: '320100' }], }, ]; return { code, options, fieldNames, }; }, };自訂選項上方內容
想要在選項清單上方加點"調料" 🧂?比如一個搜尋框、一段提示文字,或者一個可愛的小圖標?
透過插槽的魔法,你可以在每一層選項的上方添加任何你想要的內容,讓選擇體驗更加豐富多彩 🌈!
import { ref } from'vue'; exportdefault { setup() { const code = ref(''); const options = [ { name: '浙江省', code: '330000', items: [{ name: '杭州市', code: '330100' }], }, { name: '江苏省', code: '320000', items: [{ name: '南京市', code: '320100' }], }, ]; return { code, options, }; }, };API
Props
| 參數 | 說明 | 類型 | 預設值 |
|---|---|---|---|
| v-model | 選中項的值 | *string | number* |
| title | 頂部標題 | string | - |
| options | 可選項資料來源 | CascaderOption[] | [] |
| placeholder | 未選中時的提示文案 | string | 請選擇 |
| active-color | 選中狀態的高亮顏色 | string | #1989fa |
| swipeable | 是否開啟手勢左右滑動切換 | boolean | true | | closeable | 是否顯示關閉圖示 | boolean | true | | show-header | 是否展示標題欄 | boolean | true | | close-icon | 關閉圖示名稱或圖片連結,等同於 Icon 元件的 name 屬性 | string | cross |
| field-names | 自訂 options 結構中的欄位 | CascaderFieldNames | { text: 'text', value: 'value', children: 'children' } |
CascaderOption 資料結構
options 屬性是一個由物件構成的陣列,陣列中的每個物件配置一個可選項,物件可以包含以下值:
| 鍵名 | 說明 | 類型 |
|---|---|---|
| text | 選項文字(必填) | string |
| value | 選項對應的值(必填) | *string |
| color | 選項文字顏色 | string |
| children | 子選項清單 | CascaderOption[] |
| disabled | 是否禁用選項 | boolean |
| className | 為對應列添加額外的 class | *string |
Events
| 事件 | 說明 | 回調參數 |
|---|---|---|
| change | 選中項變化時觸發 | *{ value: string |
| finish | 全部選項選擇完成後觸發 | *{ value: string |
| close | 點擊關閉圖示時觸發 | - |
| click-tab | 點擊標籤時觸發 | tabIndex: number, title: string |
Slots
| 名稱 | 說明 | 參數 |
|---|---|---|
| title | 自訂頂部標題 | - |
| option | 自訂選項文字 | { option: CascaderOption, selected: boolean } |
| options-top | 自訂選項上方的內容 | { tabIndex: number } |
| options-bottom | 自訂選項下方的內容 | { tabIndex: number } |
類型定義
元件匯出以下類型定義:
importtype { CascaderProps, CascaderOption, CascaderFieldNames } from'vant';主題定製
樣式變數
元件提供了下列 CSS 變數,可用於自訂樣式,使用方法請參考 ConfigProvider 元件。
| 名稱 | 預設值 | 描述 |
|---|---|---|
| --van-cascader-header-height | 48px | - |
| --van-cascader-header-padding | 0 var(--van-padding-md) | - |
| --van-cascader-title-font-size | var(--van-font-size-lg) | - |
| --van-cascader-title-line-height | 20px | - |
| --van-cascader-close-icon-size | 22px | - |
| --van-cascader-close-icon-color | var(--van-gray-5) | - |
| --van-cascader-selected-icon-size | 18px | - |
| --van-cascader-tabs-height | 48px | - |
| --van-cascader-active-color | var(--van-danger-color) | - |
| --van-cascader-options-height | 384px | - |
| --van-cascader-option-disabled-color | var(--van-text-color-3) | - |
| --van-cascader-tab-color | var(--van-text-color) | - |
| --van-cascader-unselected-tab-color | var(--van-text-color-2) | - |
🎯 最佳實踐
💡 使用場景推薦
Cascader 就像一個萬能的「分類大師」,在各種場景下都能發揮重要作用:
🏠 地址選擇
<!-- 經典的省市區三級聯動 -->
<van-cascader
v-model="addressCode"
title="選擇地址"
:options="areaOptions"
@finish="onAddressFinish"
/>🏢 組織架構選擇
<!-- 公司部門層級選擇 -->
<van-cascader
v-model="departmentId"
title="選擇部門"
:options="departmentOptions"
placeholder="請選擇所屬部門"
/>📱 商品分類篩選
<!-- 電商商品分類選擇 -->
<van-cascader
v-model="categoryId"
title="商品分類"
:options="categoryOptions"
active-color="#ff6034"
/>📚 知識分類導航
<!-- 文檔或知識庫分類 -->
<van-cascader
v-model="topicId"
title="選擇主題"
:options="topicOptions"
:field-names="{ text: 'title', value: 'id', children: 'subTopics' }"
/>⚡ 效能最佳化小貼士
- 資料懶載入:對於大量資料,使用非同步載入避免首次渲染卡頓
- 合理的層級深度:建議控制在 3-4 層,過深會影響使用者體驗
- 資料快取:對於相對固定的資料(如地區資訊),可以進行本地快取
- 虛擬滾動:當單層選項過多時,考慮使用虛擬滾動最佳化效能
🎨 設計建議
- 層級指示:清晰的標籤頁設計讓使用者知道目前選擇的層級
- 選中狀態:明顯的選中狀態回饋,讓使用者清楚自己的選擇
- 載入狀態:非同步載入時提供友好的載入提示
- 錯誤處理:網路異常時提供重試機制和錯誤提示
🔧 常見問題解決
Q: 如何實現搜尋功能? A: 可以透過 options-top 插槽新增搜尋框,結合資料過濾實現搜尋。
Q: 如何設定預設選中值? A: 設定 v-model 的初始值為目標選項的 value 即可。
Q: 非同步載入失敗怎麼辦? A: 在 change 事件中新增錯誤處理,提供重試按鈕或錯誤提示。
Q: 如何限制選擇層級? A: 可以在資料結構中控制 children 的層級深度,或在 change 事件中進行判斷。
🎪 進階用法範例
動態禁用選項
// 根據業務邏輯動態禁用某些選項
const processOptions = (options, parentValue) => {
return options.map(option => ({
...option,
disabled: shouldDisableOption(option, parentValue),
children: option.children ? processOptions(option.children, option.value) : []
}));
};自訂選項渲染
<van-cascader v-model="value" :options="options">
<template #option="{ option, selected }">
<div class="custom-option">
<span>{{ option.text }}</span>
<van-icon v-if="option.hot" name="fire" color="red" />
<van-tag v-if="selected" size="mini" type="primary">已選</van-tag>
</div>
</template>
</van-cascader>🔗 相關元件
- Picker 選擇器 - 單列或多列選擇器
- DatePicker 日期選擇 - 專門的日期時間選擇
- Area 省市區選擇 - 專門的地區選擇元件
- TreeSelect 分類選擇 - 樹形結構的分類選擇
- Field 輸入框 - 常與 Cascader 配合使用
- Popup 彈出層 - Cascader 的容器元件
📚 延伸閱讀
💡 小提示:好的級聯選擇器就像一個優秀的導遊,不僅要知道路怎麼走,還要讓遊客在選擇的過程中感到輕鬆愉快。合理運用 Cascader 的各種特性,可以讓複雜的資料選擇變得簡單而有趣!