Skip to content
API 风格:

Cascader ​

LhCascader allows selecting from hierarchical data.

Basic Usage ​

Basic Usage
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhCascader } from '@lh-ui/vue3'

const cascaderVal = ref([])
const cascaderOpts = [
  {
    value: 'area',
    label: 'Area',
    children: [
      { value: 'beijing', label: 'Beijing' },
      { value: 'shanghai', label: 'Shanghai' },
    ],
  },
]
</script>

<template>
  <!-- Basic usage -->
  <LhCascader v-model="cascaderVal" :options="cascaderOpts" placeholder="Please select" />
</template>
vue
<script>
import { LhCascader } from '@lh-ui/vue3'

export default {
  components: { LhCascader },
  data() {
    return {
      cascaderVal: [],
      cascaderOpts: [
        {
          value: 'area',
          label: 'Area',
          children: [
            { value: 'beijing', label: 'Beijing' },
            { value: 'shanghai', label: 'Shanghai' },
          ],
        },
      ],
    }
  },
}
</script>

<template>
  <!-- Basic usage -->
  <LhCascader v-model="cascaderVal" :options="cascaderOpts" placeholder="Please select" />
</template>

Type Definitions ​

The TypeScript type structures exported by this component (auto-extracted from packages/components/cascader/src/types.ts and @lh-ui/share/core/* sources; click each entry to expand; see the Props table above for attribute descriptions):

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?: LhSxProps
}
LhCascaderItemConfig (from @lh-ui/share/core/cascader)
ts
export interface LhCascaderItemConfig {
  value?: string
  label?: string
  children?: string
  disabled?: string
  leaf?: string
}
LhCascaderNode (from @lh-ui/share/core/cascader)
ts
export interface LhCascaderNode {
  value: string | number
  label: string
  disabled?: boolean
  leaf?: boolean
  children?: LhCascaderNode[]
}
LhComponentSize (from @lh-ui/share/core/shared)
ts
export type LhComponentSize = (typeof LH_SIZE_CONST)[keyof typeof LH_SIZE_CONST]

Multi-select Mode ​

Enable multi-select to choose multiple results.

Multi-select Mode
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhCascader } from '@lh-ui/vue3'

const multiVal = ref([])
const multiOpts = [
  {
    value: 'zhinan',
    label: 'Guide',
    children: [
      { value: 'sheji', label: 'Design Guide' },
      { value: 'shejiguize', label: 'Design Rules' },
    ],
  },
  {
    value: 'zujian',
    label: 'Components',
    children: [
      { value: 'jiben', label: 'Basic' },
      { value: 'fankui', label: 'Feedback' },
    ],
  },
]
</script>

<template>
  <!-- Multi-select mode -->
  <LhCascader v-model="multiVal" :options="multiOpts" multiple />
</template>
vue
<script>
import { LhCascader } from '@lh-ui/vue3'

export default {
  components: { LhCascader },
  data() {
    return {
      multiVal: [],
      multiOpts: [
        {
          value: 'zhinan',
          label: 'Guide',
          children: [
            { value: 'sheji', label: 'Design Guide' },
            { value: 'shejiguize', label: 'Design Rules' },
          ],
        },
        {
          value: 'zujian',
          label: 'Components',
          children: [
            { value: 'jiben', label: 'Basic' },
            { value: 'fankui', label: 'Feedback' },
          ],
        },
      ],
    }
  },
}
</script>

<template>
  <!-- Multi-select mode -->
  <LhCascader v-model="multiVal" :options="multiOpts" multiple />
</template>

Disabled Options ​

Disable nodes via the disabled property.

Disabled Options
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhCascader } from '@lh-ui/vue3'

const disabledVal = ref([])
const disabledOpts = [
  {
    value: 'zhinan',
    label: 'Guide',
    disabled: true,
    children: [
      { value: 'sheji', label: 'Design Guide' },
    ],
  },
  {
    value: 'zujian',
    label: 'Components',
    children: [
      { value: 'jiben', label: 'Basic' },
      { value: 'fankui', label: 'Feedback', disabled: true },
    ],
  },
]
</script>

<template>
  <!-- Disabled options -->
  <LhCascader v-model="disabledVal" :options="disabledOpts" />
</template>
vue
<script>
import { LhCascader } from '@lh-ui/vue3'

export default {
  components: { LhCascader },
  data() {
    return {
      disabledVal: [],
      disabledOpts: [
        {
          value: 'zhinan',
          label: 'Guide',
          disabled: true,
          children: [
            { value: 'sheji', label: 'Design Guide' },
          ],
        },
        {
          value: 'zujian',
          label: 'Components',
          children: [
            { value: 'jiben', label: 'Basic' },
            { value: 'fankui', label: 'Feedback', disabled: true },
          ],
        },
      ],
    }
  },
}
</script>

<template>
  <!-- Disabled options -->
  <LhCascader v-model="disabledVal" :options="disabledOpts" />
</template>

Size, Disabled & Read-only ​

Use size to adjust the size, disabled to disable the whole selector, readonly for read-only display, placeholder for custom placeholder text, and clearable: false to hide the clear button.

Size, Disabled & Read-only
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhCascader } from '@lh-ui/vue3'

const enCascSize = ref([])
const enCascSize2 = ref([])
const enCascDisabled = ref([])
const enCascReadonly = ref([])
const enCascPlaceholder = ref([])
const enCascNoClear = ref([])
const enCascOpts = [
  {
    value: 'guide',
    label: 'Guide',
    children: [
      { value: 'design', label: 'Design Guide' },
      { value: 'rules', label: 'Design Rules' },
    ],
  },
  {
    value: 'components',
    label: 'Components',
    children: [
      { value: 'basic', label: 'Basic' },
      { value: 'feedback', label: 'Feedback' },
    ],
  },
]
</script>

<template>
  <!-- small -->
  <LhCascader v-model="enCascSize" :options="enCascOpts" size="small" placeholder="small" />
  <!-- large -->
  <LhCascader v-model="enCascSize2" :options="enCascOpts" size="large" placeholder="large" />
  <!-- Disabled -->
  <LhCascader v-model="enCascDisabled" :options="enCascOpts" disabled placeholder="Disabled" />
  <!-- Read-only -->
  <LhCascader v-model="enCascReadonly" :options="enCascOpts" readonly placeholder="Read-only" />
  <!-- Custom placeholder -->
  <LhCascader v-model="enCascPlaceholder" :options="enCascOpts" placeholder="Custom placeholder" />
  <!-- Not clearable -->
  <LhCascader v-model="enCascNoClear" :options="enCascOpts" :clearable="false" placeholder="Not clearable" />
</template>
vue
<script>
import { LhCascader } from '@lh-ui/vue3'

export default {
  components: { LhCascader },
  data() {
    return {
      enCascSize: [],
      enCascSize2: [],
      enCascDisabled: [],
      enCascReadonly: [],
      enCascPlaceholder: [],
      enCascNoClear: [],
      enCascOpts: [
        {
          value: 'guide',
          label: 'Guide',
          children: [
            { value: 'design', label: 'Design Guide' },
            { value: 'rules', label: 'Design Rules' },
          ],
        },
        {
          value: 'components',
          label: 'Components',
          children: [
            { value: 'basic', label: 'Basic' },
            { value: 'feedback', label: 'Feedback' },
          ],
        },
      ],
    }
  },
}
</script>

<template>
  <!-- small -->
  <LhCascader v-model="enCascSize" :options="enCascOpts" size="small" placeholder="small" />
  <!-- large -->
  <LhCascader v-model="enCascSize2" :options="enCascOpts" size="large" placeholder="large" />
  <!-- Disabled -->
  <LhCascader v-model="enCascDisabled" :options="enCascOpts" disabled placeholder="Disabled" />
  <!-- Read-only -->
  <LhCascader v-model="enCascReadonly" :options="enCascOpts" readonly placeholder="Read-only" />
  <!-- Custom placeholder -->
  <LhCascader v-model="enCascPlaceholder" :options="enCascOpts" placeholder="Custom placeholder" />
  <!-- Not clearable -->
  <LhCascader v-model="enCascNoClear" :options="enCascOpts" :clearable="false" placeholder="Not clearable" />
</template>
  • show-all-levels controls whether the input shows the full path (defaults to true; when off only the leaf label is shown);
  • separator customizes the level separator (the search result panel honors it too);
  • emit-path: false binds only the leaf value to v-model, while the input still echoes the full path;
  • check-strictly allows selecting nodes at any level (a click selects directly; browse children via hover expansion);
  • filterable enables search, listing matches as full paths;
  • collapse-tags collapses tags in multi-select mode;
  • cascading: false disables parent-child linkage in multi-select mode;
  • item-config aliases the node fields (e.g. building the tree from id / name), and the path echo honors it as well.

All examples below ship pre-selected values so the display differences are visible without clicking through levels: full path Zhejiang/Hangzhou/West Lake, leaf only West Lake, and Zhejiang > Hangzhou > West Lake with separator=" > ".

Path Display & Search
Zhejiang/Hangzhou/West Lake
+1
Zhejiang/Hangzhou/West Lake
Zhejiang/Hangzhou/Binjiang
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhCascader } from '@lh-ui/vue3'

const enCascFullPath = ref(['zhejiang', 'hangzhou', 'xihu'])
const enCascAllLevels = ref(['zhejiang', 'hangzhou', 'xihu'])
const enCascSep = ref(['zhejiang', 'hangzhou', 'xihu'])
const enCascEmit = ref(['xihu'])
const enCascStrict = ref(['zhejiang', 'hangzhou'])
const enCascFilter = ref([])
const enCascCollapse = ref(['xihu', 'haishu'])
const enCascLoose = ref(['xihu', 'binjiang'])
const enCascItem = ref(['zhejiang', 'hangzhou', 'xihu'])

const enPathOpts = [
  {
    value: 'zhejiang',
    label: 'Zhejiang',
    children: [
      {
        value: 'hangzhou',
        label: 'Hangzhou',
        children: [
          { value: 'xihu', label: 'West Lake' },
          { value: 'binjiang', label: 'Binjiang' },
        ],
      },
      {
        value: 'ningbo',
        label: 'Ningbo',
        children: [{ value: 'haishu', label: 'Haishu' }],
      },
    ],
  },
  {
    value: 'jiangsu',
    label: 'Jiangsu',
    children: [
      {
        value: 'nanjing',
        label: 'Nanjing',
        children: [{ value: 'xuanwu', label: 'Xuanwu' }],
      },
    ],
  },
]

const enAliasedOpts = [
  {
    id: 'zhejiang',
    name: 'Zhejiang',
    sub: [
      {
        id: 'hangzhou',
        name: 'Hangzhou',
        sub: [
          { id: 'xihu', name: 'West Lake' },
          { id: 'binjiang', name: 'Binjiang' },
        ],
      },
      {
        id: 'ningbo',
        name: 'Ningbo',
        sub: [{ id: 'haishu', name: 'Haishu' }],
      },
    ],
  },
]
</script>

<template>
  <!-- Full path (default) -->
  <LhCascader v-model="enCascFullPath" :options="enPathOpts" placeholder="Full path (default)" />
  <!-- Leaf only -->
  <LhCascader v-model="enCascAllLevels" :options="enPathOpts" :show-all-levels="false" placeholder="Leaf only" />
  <!-- Separator > -->
  <LhCascader v-model="enCascSep" :options="enPathOpts" separator=" > " placeholder="Separator >" />
  <!-- Leaf value only -->
  <LhCascader v-model="enCascEmit" :options="enPathOpts" :emit-path="false" placeholder="Leaf value only" />
  <!-- Any level selectable -->
  <LhCascader v-model="enCascStrict" :options="enPathOpts" check-strictly placeholder="Any level selectable" />
  <!-- Searchable -->
  <LhCascader v-model="enCascFilter" :options="enPathOpts" filterable placeholder="Searchable" />
  <!-- Collapse tags -->
  <LhCascader v-model="enCascCollapse" :options="enPathOpts" multiple collapse-tags placeholder="Collapse tags" />
  <!-- No linkage -->
  <LhCascader v-model="enCascLoose" :options="enPathOpts" multiple :cascading="false" placeholder="No linkage" />
  <!-- Field aliases -->
  <LhCascader v-model="enCascItem" :options="enAliasedOpts" :item-config="{ value: 'id', label: 'name', children: 'sub' }" placeholder="Field aliases" />
</template>
vue
<script>
import { LhCascader } from '@lh-ui/vue3'

export default {
  components: { LhCascader },
  data() {
    return {
      enCascFullPath: ['zhejiang', 'hangzhou', 'xihu'],
      enCascAllLevels: ['zhejiang', 'hangzhou', 'xihu'],
      enCascSep: ['zhejiang', 'hangzhou', 'xihu'],
      enCascEmit: ['xihu'],
      enCascStrict: ['zhejiang', 'hangzhou'],
      enCascFilter: [],
      enCascCollapse: ['xihu', 'haishu'],
      enCascLoose: ['xihu', 'binjiang'],
      enCascItem: ['zhejiang', 'hangzhou', 'xihu'],
      enPathOpts: [
        {
          value: 'zhejiang',
          label: 'Zhejiang',
          children: [
            {
              value: 'hangzhou',
              label: 'Hangzhou',
              children: [
                { value: 'xihu', label: 'West Lake' },
                { value: 'binjiang', label: 'Binjiang' },
              ],
            },
            {
              value: 'ningbo',
              label: 'Ningbo',
              children: [{ value: 'haishu', label: 'Haishu' }],
            },
          ],
        },
        {
          value: 'jiangsu',
          label: 'Jiangsu',
          children: [
            {
              value: 'nanjing',
              label: 'Nanjing',
              children: [{ value: 'xuanwu', label: 'Xuanwu' }],
            },
          ],
        },
      ],
      enAliasedOpts: [
        {
          id: 'zhejiang',
          name: 'Zhejiang',
          sub: [
            {
              id: 'hangzhou',
              name: 'Hangzhou',
              sub: [
                { id: 'xihu', name: 'West Lake' },
                { id: 'binjiang', name: 'Binjiang' },
              ],
            },
            {
              id: 'ningbo',
              name: 'Ningbo',
              sub: [{ id: 'haishu', name: 'Haishu' }],
            },
          ],
        },
      ],
    }
  },
}
</script>

<template>
  <!-- Full path (default) -->
  <LhCascader v-model="enCascFullPath" :options="enPathOpts" placeholder="Full path (default)" />
  <!-- Leaf only -->
  <LhCascader v-model="enCascAllLevels" :options="enPathOpts" :show-all-levels="false" placeholder="Leaf only" />
  <!-- Separator > -->
  <LhCascader v-model="enCascSep" :options="enPathOpts" separator=" > " placeholder="Separator >" />
  <!-- Leaf value only -->
  <LhCascader v-model="enCascEmit" :options="enPathOpts" :emit-path="false" placeholder="Leaf value only" />
  <!-- Any level selectable -->
  <LhCascader v-model="enCascStrict" :options="enPathOpts" check-strictly placeholder="Any level selectable" />
  <!-- Searchable -->
  <LhCascader v-model="enCascFilter" :options="enPathOpts" filterable placeholder="Searchable" />
  <!-- Collapse tags -->
  <LhCascader v-model="enCascCollapse" :options="enPathOpts" multiple collapse-tags placeholder="Collapse tags" />
  <!-- No linkage -->
  <LhCascader v-model="enCascLoose" :options="enPathOpts" multiple :cascading="false" placeholder="No linkage" />
  <!-- Field aliases -->
  <LhCascader v-model="enCascItem" :options="enAliasedOpts" :item-config="{ value: 'id', label: 'name', children: 'sub' }" placeholder="Field aliases" />
</template>

Props ​

PropDescriptionTypeDefault
modelValueBound value(string | number)[]() => []
optionsOptions data[LhCascaderNode](#type-LhCascaderNode)[]() => []
sizeSize"small" | "medium" | "large" | "mini" | "x-large"'medium'
disabledDisabledbooleanfalse
clearableClearablebooleantrue
placeholderPlaceholder text (falls back to the cascader.placeholder locale message when unset)string''
readonlyRead-onlybooleanfalse
showAllLevelsShow full path in inputbooleantrue
checkStrictlyAny level node selectablebooleanfalse
emitPathReturn value includes full pathbooleantrue
multipleMulti-selectbooleanfalse
cascadingCascading linkagebooleantrue
separatorLevel separatorstring'/'
collapseTagsCollapse tags in multi-select modebooleanfalse
filterableSearchablebooleanfalse
itemConfig—[LhCascaderItemConfig](#type-LhCascaderItemConfig)() => ({})
sxShorthand layout props (e.g. { mt: 2, w: '50%' }), applied as inline styles on the trigger root element (the floating panel is not affected)LhSxProps—

Events ​

EventDescriptionCallback
update:modelValueValue changed(value: (string | number)[]) => void
changeSelection changed(value: (string | number)[], path: LhCascaderNode[] | null) => void

Data Structure ​

LhCascaderNode type definition:

ts
interface LhCascaderNode {
  value: string | number
  label: string
  disabled?: boolean
  leaf?: boolean
  children?: LhCascaderNode[]
}

Slots ​

SlotDescriptionDefault
no-matchCustom content when the filter matches nothingLocale message cascader.noMatch ("No matching data")

Beauty of tradition, foundation of code