Skip to content
API 风格:

Каскадный выбор ​

Каскадный выбор применяется для данных с несколькими уровнями иерархии — например, выбор провинции, города и района.

Базовое использование ​

Самостоятельное использование
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 позволяет выбирать узел на любом уровне (клик по любому уровню сразу выбирает его, а просмотр дочерних уровней разворачивается при наведении);
  • 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
/**
 * Отображение свойства item в props Cascader
 */
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 (в китайском —「无匹配数据」)

Красота традиций — основа кода