Cascader 級聯選擇器
級聯選擇器用於多層級資料的場景,例如:省市地區選擇。
基礎用法
獨立使用
vue
<script setup>
import { ref } from 'vue'
const value1 = ref([])
const options1 = [
{
value: 'zhinan',
label: '指南',
children: [
{
value: 'sheji',
label: '设计指南',
children: [
{ value: 'yuansze', label: '颜色' },
{ value: 'fuziyuanze', label: '字体' },
],
},
{
value: 'shejiguize',
label: '设计规则',
},
],
},
{
value: 'zujian',
label: '组件',
children: [
{ value: 'jiben', label: '基础' },
{ value: 'fankui', label: '反馈' },
],
},
]
</script>
<template>
<!-- 基礎用法 -->
<lh-cascader v-model="value1" :options="options1" />
</template>vue
<script>
export default {
data() {
return {
value1: [],
options1: [
{
value: 'zhinan',
label: '指南',
children: [
{
value: 'sheji',
label: '设计指南',
children: [
{ value: 'yuansze', label: '颜色' },
{ value: 'fuziyuanze', label: '字体' },
],
},
{
value: 'shejiguize',
label: '设计规则',
},
],
},
{
value: 'zujian',
label: '组件',
children: [
{ value: 'jiben', label: '基础' },
{ value: 'fankui', label: '反馈' },
],
},
],
}
},
}
</script>
<template>
<!-- 基礎用法 -->
<lh-cascader v-model="value1" :options="options1" />
</template>多選模式
設定為多選模式,可以選擇多個結果。
多選模式
vue
<script setup>
import { ref } from 'vue'
const value2 = ref([])
const options2 = [
{
value: 'zhinan',
label: '指南',
children: [
{ value: 'sheji', label: '设计指南' },
{ value: 'shejiguize', label: '设计规则' },
],
},
{
value: 'zujian',
label: '组件',
children: [
{ value: 'jiben', label: '基础组件' },
{ value: 'fankui', label: '反馈组件' },
],
},
]
</script>
<template>
<!-- 多選模式 -->
<lh-cascader v-model="value2" :options="options2" multiple />
</template>vue
<script>
export default {
data() {
return {
value2: [],
options2: [
{
value: 'zhinan',
label: '指南',
children: [
{ value: 'sheji', label: '设计指南' },
{ value: 'shejiguize', label: '设计规则' },
],
},
{
value: 'zujian',
label: '组件',
children: [
{ value: 'jiben', label: '基础组件' },
{ value: 'fankui', label: '反馈组件' },
],
},
],
}
},
}
</script>
<template>
<!-- 多選模式 -->
<lh-cascader v-model="value2" :options="options2" multiple />
</template>選項停用
透過 disabled 屬性停用節點。
選項停用
vue
<script setup>
import { ref } from 'vue'
const value3 = ref([])
const options3 = [
{
value: 'zhinan',
label: '指南',
disabled: true,
children: [
{ value: 'sheji', label: '设计指南' },
],
},
{
value: 'zujian',
label: '组件',
children: [
{ value: 'jiben', label: '基础组件' },
{ value: 'fankui', label: '反馈组件', disabled: true },
],
},
]
</script>
<template>
<!-- 選項停用 -->
<lh-cascader v-model="value3" :options="options3" />
</template>vue
<script>
export default {
data() {
return {
value3: [],
options3: [
{
value: 'zhinan',
label: '指南',
disabled: true,
children: [
{ value: 'sheji', label: '设计指南' },
],
},
{
value: 'zujian',
label: '组件',
children: [
{ value: 'jiben', label: '基础组件' },
{ value: 'fankui', label: '反馈组件', disabled: true },
],
},
],
}
},
}
</script>
<template>
<!-- 選項停用 -->
<lh-cascader v-model="value3" :options="options3" />
</template>尺寸、停用與唯讀
透過 size 調整尺寸,disabled 停用整個選擇器,readonly 唯讀展示,placeholder 自訂佔位符,clearable 關閉清除按鈕。
尺寸、停用與唯讀
vue
<script setup lang="ts">
import { ref } from 'vue'
const demoCascSize = ref([])
const demoCascSize2 = ref([])
const demoCascDisabled = ref([])
const demoCascReadonly = ref([])
const demoCascPlaceholder = ref([])
const demoCascNoClear = ref([])
const options = [
{
value: 'zhinan',
label: '指南',
children: [
{ value: 'sheji', label: '设计指南' },
{ value: 'shejiguize', label: '设计规则' },
],
},
{
value: 'zujian',
label: '组件',
children: [
{ value: 'jiben', label: '基础组件' },
{ value: 'fankui', label: '反馈组件' },
],
},
]
</script>
<template>
<!-- small -->
<lh-cascader v-model="demoCascSize" :options="options" size="small" placeholder="small" />
<!-- large -->
<lh-cascader v-model="demoCascSize2" :options="options" size="large" placeholder="large" />
<!-- 停用狀態 -->
<lh-cascader v-model="demoCascDisabled" :options="options" disabled placeholder="禁用状态" />
<!-- 唯讀狀態 -->
<lh-cascader v-model="demoCascReadonly" :options="options" readonly placeholder="只读状态" />
<!-- 自訂佔位符 -->
<lh-cascader v-model="demoCascPlaceholder" :options="options" placeholder="自定义占位符" />
<!-- 不可清除 -->
<lh-cascader v-model="demoCascNoClear" :options="options" :clearable="false" placeholder="不可清除" />
</template>vue
<script>
export default {
data() {
return {
demoCascSize: [],
demoCascSize2: [],
demoCascDisabled: [],
demoCascReadonly: [],
demoCascPlaceholder: [],
demoCascNoClear: [],
options: [
{
value: 'zhinan',
label: '指南',
children: [
{ value: 'sheji', label: '设计指南' },
{ value: 'shejiguize', label: '设计规则' },
],
},
{
value: 'zujian',
label: '组件',
children: [
{ value: 'jiben', label: '基础组件' },
{ value: 'fankui', label: '反馈组件' },
],
},
],
}
},
}
</script>
<template>
<!-- small -->
<lh-cascader v-model="demoCascSize" :options="options" size="small" placeholder="small" />
<!-- large -->
<lh-cascader v-model="demoCascSize2" :options="options" size="large" placeholder="large" />
<!-- 停用狀態 -->
<lh-cascader v-model="demoCascDisabled" :options="options" disabled placeholder="禁用状态" />
<!-- 唯讀狀態 -->
<lh-cascader v-model="demoCascReadonly" :options="options" readonly placeholder="只读状态" />
<!-- 自訂佔位符 -->
<lh-cascader v-model="demoCascPlaceholder" :options="options" placeholder="自定义占位符" />
<!-- 不可清除 -->
<lh-cascader v-model="demoCascNoClear" :options="options" :clearable="false" placeholder="不可清除" />
</template>路徑顯示與搜尋
show-all-levels控制輸入框是否顯示完整路徑(預設true,關閉後只顯示末級名稱);separator自訂路徑分隔符號,搜尋結果面板同樣生效;emit-path設為false時v-model只綁定末級節點的值,輸入框仍回顯完整路徑;check-strictly允許選中任意層級節點(點選任意層級直接選中,瀏覽子級依賴 hover 展開);filterable開啟搜尋,輸入關鍵字後按完整路徑展示匹配項;collapse-tags在多選模式下折疊標籤;cascading關閉父子節點連動勾選;item-config自訂節點欄位別名(如以id/name建樹),路徑回顯同樣生效。
以下示例均預置了選中值,無需逐級點選即可對比展示差異:完整路徑顯示 浙江省/杭州市/西湖區,關閉 show-all-levels 後只顯示 西湖區,separator=" > " 時顯示 浙江省 > 杭州市 > 西湖區。
路徑顯示與搜尋
vue
<script setup lang="ts">
import { ref } from 'vue'
const demoCascFullPath = ref(['zhejiang', 'hangzhou', 'xihu'])
const demoCascAllLevels = ref(['zhejiang', 'hangzhou', 'xihu'])
const demoCascSep = ref(['zhejiang', 'hangzhou', 'xihu'])
const demoCascEmit = ref(['xihu'])
const demoCascStrict = ref(['zhejiang', 'hangzhou'])
const demoCascFilter = ref([])
const demoCascCollapse = ref(['xihu', 'haishu'])
const demoCascLoose = ref(['xihu', 'binjiang'])
const demoCascItem = ref(['zhejiang', 'hangzhou', 'xihu'])
const pathOptions = [
{
value: 'zhejiang',
label: '浙江省',
children: [
{
value: 'hangzhou',
label: '杭州市',
children: [
{ value: 'xihu', label: '西湖区' },
{ value: 'binjiang', label: '滨江区' },
],
},
{
value: 'ningbo',
label: '宁波市',
children: [{ value: 'haishu', label: '海曙区' }],
},
],
},
{
value: 'jiangsu',
label: '江苏省',
children: [
{
value: 'nanjing',
label: '南京市',
children: [{ value: 'xuanwu', label: '玄武区' }],
},
],
},
]
const aliasedOptions = [
{
id: 'zhejiang',
name: '浙江省',
sub: [
{
id: 'hangzhou',
name: '杭州市',
sub: [
{ id: 'xihu', name: '西湖区' },
{ id: 'binjiang', name: '滨江区' },
],
},
{
id: 'ningbo',
name: '宁波市',
sub: [{ id: 'haishu', name: '海曙区' }],
},
],
},
]
</script>
<template>
<!-- 完整路徑(預設) -->
<lh-cascader v-model="demoCascFullPath" :options="pathOptions" placeholder="完整路径(默认)" />
<!-- 只顯示末級 -->
<lh-cascader v-model="demoCascAllLevels" :options="pathOptions" :show-all-levels="false" placeholder="只显示末级" />
<!-- 分隔符號 > -->
<lh-cascader v-model="demoCascSep" :options="pathOptions" separator=" > " placeholder="分隔符 >" />
<!-- 僅返回末級值 -->
<lh-cascader v-model="demoCascEmit" :options="pathOptions" :emit-path="false" placeholder="仅返回末级值" />
<!-- 任意層級可選 -->
<lh-cascader v-model="demoCascStrict" :options="pathOptions" check-strictly placeholder="任意层级可选" />
<!-- 可搜尋 -->
<lh-cascader v-model="demoCascFilter" :options="pathOptions" filterable placeholder="可搜索" />
<!-- 多選折疊標籤 -->
<lh-cascader v-model="demoCascCollapse" :options="pathOptions" multiple collapse-tags placeholder="多选折叠标签" />
<!-- 父子不連動 -->
<lh-cascader v-model="demoCascLoose" :options="pathOptions" multiple :cascading="false" placeholder="父子不联动" />
<!-- 欄位別名 -->
<lh-cascader v-model="demoCascItem" :options="aliasedOptions" :item-config="{ value: 'id', label: 'name', children: 'sub' }" placeholder="字段别名" />
</template>vue
<script>
export default {
data() {
return {
demoCascFullPath: ['zhejiang', 'hangzhou', 'xihu'],
demoCascAllLevels: ['zhejiang', 'hangzhou', 'xihu'],
demoCascSep: ['zhejiang', 'hangzhou', 'xihu'],
demoCascEmit: ['xihu'],
demoCascStrict: ['zhejiang', 'hangzhou'],
demoCascFilter: [],
demoCascCollapse: ['xihu', 'haishu'],
demoCascLoose: ['xihu', 'binjiang'],
demoCascItem: ['zhejiang', 'hangzhou', 'xihu'],
pathOptions: [
{
value: 'zhejiang',
label: '浙江省',
children: [
{
value: 'hangzhou',
label: '杭州市',
children: [
{ value: 'xihu', label: '西湖区' },
{ value: 'binjiang', label: '滨江区' },
],
},
{
value: 'ningbo',
label: '宁波市',
children: [{ value: 'haishu', label: '海曙区' }],
},
],
},
{
value: 'jiangsu',
label: '江苏省',
children: [
{
value: 'nanjing',
label: '南京市',
children: [{ value: 'xuanwu', label: '玄武区' }],
},
],
},
],
aliasedOptions: [
{
id: 'zhejiang',
name: '浙江省',
sub: [
{
id: 'hangzhou',
name: '杭州市',
sub: [
{ id: 'xihu', name: '西湖区' },
{ id: 'binjiang', name: '滨江区' },
],
},
{
id: 'ningbo',
name: '宁波市',
sub: [{ id: 'haishu', name: '海曙区' }],
},
],
},
],
}
},
}
</script>
<template>
<!-- 完整路徑(預設) -->
<lh-cascader v-model="demoCascFullPath" :options="pathOptions" placeholder="完整路径(默认)" />
<!-- 只顯示末級 -->
<lh-cascader v-model="demoCascAllLevels" :options="pathOptions" :show-all-levels="false" placeholder="只显示末级" />
<!-- 分隔符號 > -->
<lh-cascader v-model="demoCascSep" :options="pathOptions" separator=" > " placeholder="分隔符 >" />
<!-- 僅返回末級值 -->
<lh-cascader v-model="demoCascEmit" :options="pathOptions" :emit-path="false" placeholder="仅返回末级值" />
<!-- 任意層級可選 -->
<lh-cascader v-model="demoCascStrict" :options="pathOptions" check-strictly placeholder="任意层级可选" />
<!-- 可搜尋 -->
<lh-cascader v-model="demoCascFilter" :options="pathOptions" filterable placeholder="可搜索" />
<!-- 多選折疊標籤 -->
<lh-cascader v-model="demoCascCollapse" :options="pathOptions" multiple collapse-tags placeholder="多选折叠标签" />
<!-- 父子不連動 -->
<lh-cascader v-model="demoCascLoose" :options="pathOptions" multiple :cascading="false" placeholder="父子不联动" />
<!-- 欄位別名 -->
<lh-cascader v-model="demoCascItem" :options="aliasedOptions" :item-config="{ value: 'id', label: 'name', children: 'sub' }" placeholder="字段别名" />
</template>Props
| 屬性 | 說明 | 類型 | 預設值 |
|---|---|---|---|
| modelValue | 綁定值 | (string | number)[] | () => [] |
| options | 選項列表 | [LhCascaderNode](#type-LhCascaderNode)[] | () => [] |
| size | 尺寸 | "small" | "medium" | "large" | "mini" | "x-large" | 'medium' |
| disabled | 是否停用 | boolean | false |
| clearable | 是否可清除 | boolean | true |
| placeholder | 佔位符(未傳時取語言包 cascader.placeholder,中文「請選擇」) | string | '' |
| readonly | 是否唯讀 | boolean | false |
| showAllLevels | 是否在輸入框顯示完整路徑 | boolean | true |
| checkStrictly | 任意層級節點可選 | boolean | false |
| emitPath | 返回值是否包含完整路徑 | boolean | true |
| multiple | 是否多選 | boolean | false |
| cascading | 是否級聯關聯 | boolean | true |
| separator | 分隔符號 | string | '/' |
| collapseTags | 多選模式下是否折疊標籤 | boolean | false |
| filterable | 是否可搜尋 | boolean | false |
| itemConfig | 節點欄位別名 | [LhCascaderItemConfig](#type-LhCascaderItemConfig) | () => ({}) |
| sx | 快速版面配置屬性(如 { mt: 2, w: '50%' }),轉內聯樣式作用於觸發器根元素(浮層面板不受影響) | LhSxProps | — |
Events
| 事件名 | 說明 | 回呼參數 |
|---|---|---|
| change | 選中值變化時觸發 | (value: (string | number)[], path: LhCascaderNode[] | null) |
| update:model-value | 綁定值變化時觸發 | value: (string | number)[] |
資料結構
LhCascaderNode 類型定義:
ts
interface LhCascaderNode {
value: string | number
label: string
disabled?: boolean
leaf?: boolean
children?: LhCascaderNode[]
}類型定義
本元件對外匯出的 TypeScript 類型結構如下(自動提取自 packages/components/cascader/src/types.ts 與 @lh-ui/share/core/* 原始碼,點選各條目展開檢視完整定義;屬性說明見上方 Props 表):
LhCascaderProps
ts
export interface LhCascaderProps {
modelValue?: (string | number)[]
options?: LhCascaderNode[]
size?: LhComponentSize
disabled?: boolean
clearable?: boolean
placeholder?: string
readonly?: boolean
showAllLevels?: boolean
checkStrictly?: boolean
emitPath?: boolean
multiple?: boolean
cascading?: boolean
separator?: string
collapseTags?: boolean
filterable?: boolean
itemConfig?: LhCascaderItemConfig
/** sx 快速版面配置屬性 */
sx?: LhSxProps
}LhCascaderItemConfig (來自 @lh-ui/share/core/cascader)
ts
/**
* Cascader props 中的 item 屬性映射
*/
export interface LhCascaderItemConfig {
value?: string
label?: string
children?: string
disabled?: string
leaf?: string
}LhCascaderNode (來自 @lh-ui/share/core/cascader)
ts
/**
* Cascader 節點
*/
export interface LhCascaderNode {
value: string | number
label: string
disabled?: boolean
leaf?: boolean
children?: LhCascaderNode[]
}LhComponentSize (來自 @lh-ui/share/core/shared)
ts
export type LhComponentSize = (typeof LH_SIZE_CONST)[keyof typeof LH_SIZE_CONST]Slots
| 插槽 | 說明 | 預設內容 |
|---|---|---|
| no-match | 篩選無匹配結果時搜尋面板的自訂內容 | 語言包 cascader.noMatch(中文「無匹配資料」) |