Skip to content
API 风格:

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=" > " 時顯示 浙江省 > 杭州市 > 西湖區。

路徑顯示與搜尋
浙江省/杭州市/西湖區
+1
浙江省/杭州市/西湖區
浙江省/杭州市/濱江區
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是否停用booleanfalse
clearable是否可清除booleantrue
placeholder佔位符(未傳時取語言包 cascader.placeholder,中文「請選擇」)string''
readonly是否唯讀booleanfalse
showAllLevels是否在輸入框顯示完整路徑booleantrue
checkStrictly任意層級節點可選booleanfalse
emitPath返回值是否包含完整路徑booleantrue
multiple是否多選booleanfalse
cascading是否級聯關聯booleantrue
separator分隔符號string'/'
collapseTags多選模式下是否折疊標籤booleanfalse
filterable是否可搜尋booleanfalse
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(中文「無匹配資料」)