Selector en cascada
El selector en cascada se usa para datos con varios niveles, por ejemplo: la selección de provincia, ciudad y distrito.
Uso básico
<script setup>
import { ref } from 'vue'
const value1 = ref([])
const options1 = [
{
value: 'zhinan',
label: 'Guía',
children: [
{
value: 'sheji',
label: 'Guía de diseño',
children: [
{ value: 'yuansze', label: 'Color' },
{ value: 'fuziyuanze', label: 'Tipografía' },
],
},
{
value: 'shejiguize',
label: 'Reglas de diseño',
},
],
},
{
value: 'zujian',
label: 'Componentes',
children: [
{ value: 'jiben', label: 'Básico' },
{ value: 'fankui', label: 'Retroalimentación' },
],
},
]
</script>
<template>
<!-- Uso básico -->
<lh-cascader v-model="value1" :options="options1" />
</template><script>
export default {
data() {
return {
value1: [],
options1: [
{
value: 'zhinan',
label: 'Guía',
children: [
{
value: 'sheji',
label: 'Guía de diseño',
children: [
{ value: 'yuansze', label: 'Color' },
{ value: 'fuziyuanze', label: 'Tipografía' },
],
},
{
value: 'shejiguize',
label: 'Reglas de diseño',
},
],
},
{
value: 'zujian',
label: 'Componentes',
children: [
{ value: 'jiben', label: 'Básico' },
{ value: 'fankui', label: 'Retroalimentación' },
],
},
],
}
},
}
</script>
<template>
<!-- Uso básico -->
<lh-cascader v-model="value1" :options="options1" />
</template>Modo de selección múltiple
Se puede establecer el modo de selección múltiple para elegir varios resultados.
<script setup>
import { ref } from 'vue'
const value2 = ref([])
const options2 = [
{
value: 'zhinan',
label: 'Guía',
children: [
{ value: 'sheji', label: 'Guía de diseño' },
{ value: 'shejiguize', label: 'Reglas de diseño' },
],
},
{
value: 'zujian',
label: 'Componentes',
children: [
{ value: 'jiben', label: 'Componentes básicos' },
{ value: 'fankui', label: 'Componentes de retroalimentación' },
],
},
]
</script>
<template>
<!-- Modo de selección múltiple -->
<lh-cascader v-model="value2" :options="options2" multiple />
</template><script>
export default {
data() {
return {
value2: [],
options2: [
{
value: 'zhinan',
label: 'Guía',
children: [
{ value: 'sheji', label: 'Guía de diseño' },
{ value: 'shejiguize', label: 'Reglas de diseño' },
],
},
{
value: 'zujian',
label: 'Componentes',
children: [
{ value: 'jiben', label: 'Componentes básicos' },
{ value: 'fankui', label: 'Componentes de retroalimentación' },
],
},
],
}
},
}
</script>
<template>
<!-- Modo de selección múltiple -->
<lh-cascader v-model="value2" :options="options2" multiple />
</template>Opción deshabilitada
Se deshabilitan los nodos con la propiedad disabled.
<script setup>
import { ref } from 'vue'
const value3 = ref([])
const options3 = [
{
value: 'zhinan',
label: 'Guía',
disabled: true,
children: [
{ value: 'sheji', label: 'Guía de diseño' },
],
},
{
value: 'zujian',
label: 'Componentes',
children: [
{ value: 'jiben', label: 'Componentes básicos' },
{ value: 'fankui', label: 'Componentes de retroalimentación', disabled: true },
],
},
]
</script>
<template>
<!-- Opción deshabilitada -->
<lh-cascader v-model="value3" :options="options3" />
</template><script>
export default {
data() {
return {
value3: [],
options3: [
{
value: 'zhinan',
label: 'Guía',
disabled: true,
children: [
{ value: 'sheji', label: 'Guía de diseño' },
],
},
{
value: 'zujian',
label: 'Componentes',
children: [
{ value: 'jiben', label: 'Componentes básicos' },
{ value: 'fankui', label: 'Componentes de retroalimentación', disabled: true },
],
},
],
}
},
}
</script>
<template>
<!-- Opción deshabilitada -->
<lh-cascader v-model="value3" :options="options3" />
</template>Tamaño, deshabilitado y solo lectura
Con size se ajusta el tamaño, disabled deshabilita todo el selector, readonly lo muestra en modo solo lectura, placeholder personaliza el marcador de posición y clearable elimina el botón de borrado.
<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: 'Guía',
children: [
{ value: 'sheji', label: 'Guía de diseño' },
{ value: 'shejiguize', label: 'Reglas de diseño' },
],
},
{
value: 'zujian',
label: 'Componentes',
children: [
{ value: 'jiben', label: 'Componentes básicos' },
{ value: 'fankui', label: 'Componentes de retroalimentación' },
],
},
]
</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" />
<!-- Deshabilitado -->
<lh-cascader v-model="demoCascDisabled" :options="options" disabled placeholder="Deshabilitado" />
<!-- Solo lectura -->
<lh-cascader v-model="demoCascReadonly" :options="options" readonly placeholder="Solo lectura" />
<!-- Marcador personalizado -->
<lh-cascader v-model="demoCascPlaceholder" :options="options" placeholder="Marcador personalizado" />
<!-- No borrable -->
<lh-cascader v-model="demoCascNoClear" :options="options" :clearable="false" placeholder="No borrable" />
</template><script>
export default {
data() {
return {
demoCascSize: [],
demoCascSize2: [],
demoCascDisabled: [],
demoCascReadonly: [],
demoCascPlaceholder: [],
demoCascNoClear: [],
options: [
{
value: 'zhinan',
label: 'Guía',
children: [
{ value: 'sheji', label: 'Guía de diseño' },
{ value: 'shejiguize', label: 'Reglas de diseño' },
],
},
{
value: 'zujian',
label: 'Componentes',
children: [
{ value: 'jiben', label: 'Componentes básicos' },
{ value: 'fankui', label: 'Componentes de retroalimentación' },
],
},
],
}
},
}
</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" />
<!-- Deshabilitado -->
<lh-cascader v-model="demoCascDisabled" :options="options" disabled placeholder="Deshabilitado" />
<!-- Solo lectura -->
<lh-cascader v-model="demoCascReadonly" :options="options" readonly placeholder="Solo lectura" />
<!-- Marcador personalizado -->
<lh-cascader v-model="demoCascPlaceholder" :options="options" placeholder="Marcador personalizado" />
<!-- No borrable -->
<lh-cascader v-model="demoCascNoClear" :options="options" :clearable="false" placeholder="No borrable" />
</template>Visualización de la ruta y búsqueda
show-all-levelscontrola si el campo de entrada muestra la ruta completa (predeterminadotrue; si se desactiva, solo se muestra el nombre del último nivel);separatorpersonaliza el separador de la ruta; también se aplica al panel de resultados de búsqueda;- si
emit-pathesfalse,v-modelsolo se vincula al valor del nodo del último nivel, aunque el campo de entrada sigue mostrando la ruta completa; check-strictlypermite seleccionar nodos de cualquier nivel (se selecciona directamente cualquier nivel; explorar los subniveles depende de pasar el puntero);filterableactiva la búsqueda; al escribir una palabra clave, las coincidencias se muestran con la ruta completa;collapse-tagspliega las etiquetas en el modo de selección múltiple;cascadingdesactiva la vinculación de la selección entre nodos padre e hijo;item-configpersonaliza los alias de los campos del nodo (p. ej., construyendo el árbol conid/name); la visualización de la ruta también funciona.
Los siguientes ejemplos tienen valores preseleccionados, de modo que pueden compararse las diferencias sin ir seleccionando nivel por nivel: con la ruta completa se muestra Zhejiang / Hangzhou / Lago del Oeste; al desactivar show-all-levels solo se muestra Lago del Oeste; con separator=" > " se muestra Zhejiang > Hangzhou > Lago del Oeste.
<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: 'Zhejiang',
children: [
{
value: 'hangzhou',
label: 'Hangzhou',
children: [
{ value: 'xihu', label: 'Lago del Oeste' },
{ 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 aliasedOptions = [
{
id: 'zhejiang',
name: 'Zhejiang',
sub: [
{
id: 'hangzhou',
name: 'Hangzhou',
sub: [
{ id: 'xihu', name: 'Lago del Oeste' },
{ id: 'binjiang', name: 'Binjiang' },
],
},
{
id: 'ningbo',
name: 'Ningbo',
sub: [{ id: 'haishu', name: 'Haishu' }],
},
],
},
]
</script>
<template>
<!-- Ruta completa (predeterminado) -->
<lh-cascader v-model="demoCascFullPath" :options="pathOptions" placeholder="Ruta completa (predeterminado)" />
<!-- Solo el último nivel -->
<lh-cascader v-model="demoCascAllLevels" :options="pathOptions" :show-all-levels="false" placeholder="Solo el último nivel" />
<!-- Separador > -->
<lh-cascader v-model="demoCascSep" :options="pathOptions" separator=" > " placeholder="Separador >" />
<!-- Solo el valor del último nivel -->
<lh-cascader v-model="demoCascEmit" :options="pathOptions" :emit-path="false" placeholder="Solo el valor del último nivel" />
<!-- Cualquier nivel seleccionable -->
<lh-cascader v-model="demoCascStrict" :options="pathOptions" check-strictly placeholder="Cualquier nivel seleccionable" />
<!-- Con búsqueda -->
<lh-cascader v-model="demoCascFilter" :options="pathOptions" filterable placeholder="Con búsqueda" />
<!-- Etiquetas plegadas en la selección múltiple -->
<lh-cascader v-model="demoCascCollapse" :options="pathOptions" multiple collapse-tags placeholder="Etiquetas plegadas en la selección múltiple" />
<!-- Padre e hijo no vinculados -->
<lh-cascader v-model="demoCascLoose" :options="pathOptions" multiple :cascading="false" placeholder="Padre e hijo no vinculados" />
<!-- Alias de campos -->
<lh-cascader v-model="demoCascItem" :options="aliasedOptions" :item-config="{ value: 'id', label: 'name', children: 'sub' }" placeholder="Alias de campos" />
</template><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: 'Zhejiang',
children: [
{
value: 'hangzhou',
label: 'Hangzhou',
children: [
{ value: 'xihu', label: 'Lago del Oeste' },
{ 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' }],
},
],
},
],
aliasedOptions: [
{
id: 'zhejiang',
name: 'Zhejiang',
sub: [
{
id: 'hangzhou',
name: 'Hangzhou',
sub: [
{ id: 'xihu', name: 'Lago del Oeste' },
{ id: 'binjiang', name: 'Binjiang' },
],
},
{
id: 'ningbo',
name: 'Ningbo',
sub: [{ id: 'haishu', name: 'Haishu' }],
},
],
},
],
}
},
}
</script>
<template>
<!-- Ruta completa (predeterminado) -->
<lh-cascader v-model="demoCascFullPath" :options="pathOptions" placeholder="Ruta completa (predeterminado)" />
<!-- Solo el último nivel -->
<lh-cascader v-model="demoCascAllLevels" :options="pathOptions" :show-all-levels="false" placeholder="Solo el último nivel" />
<!-- Separador > -->
<lh-cascader v-model="demoCascSep" :options="pathOptions" separator=" > " placeholder="Separador >" />
<!-- Solo el valor del último nivel -->
<lh-cascader v-model="demoCascEmit" :options="pathOptions" :emit-path="false" placeholder="Solo el valor del último nivel" />
<!-- Cualquier nivel seleccionable -->
<lh-cascader v-model="demoCascStrict" :options="pathOptions" check-strictly placeholder="Cualquier nivel seleccionable" />
<!-- Con búsqueda -->
<lh-cascader v-model="demoCascFilter" :options="pathOptions" filterable placeholder="Con búsqueda" />
<!-- Etiquetas plegadas en la selección múltiple -->
<lh-cascader v-model="demoCascCollapse" :options="pathOptions" multiple collapse-tags placeholder="Etiquetas plegadas en la selección múltiple" />
<!-- Padre e hijo no vinculados -->
<lh-cascader v-model="demoCascLoose" :options="pathOptions" multiple :cascading="false" placeholder="Padre e hijo no vinculados" />
<!-- Alias de campos -->
<lh-cascader v-model="demoCascItem" :options="aliasedOptions" :item-config="{ value: 'id', label: 'name', children: 'sub' }" placeholder="Alias de campos" />
</template>Props
| Prop | Descripción | Tipo | Predeterminado |
|---|---|---|---|
| modelValue | Valor vinculado | (string | number)[] | () => [] |
| options | Lista de opciones | [LhCascaderNode](#type-LhCascaderNode)[] | () => [] |
| size | Tamaño | "small" | "medium" | "large" | "mini" | "x-large" | 'medium' |
| disabled | Si se deshabilita | boolean | false |
| clearable | Si se puede borrar | boolean | true |
| placeholder | Marcador de posición (si no se pasa, se toma del paquete de idioma cascader.placeholder) | string | '' |
| readonly | Si es de solo lectura | boolean | false |
| showAllLevels | Si el campo de entrada muestra la ruta completa | boolean | true |
| checkStrictly | Nodos seleccionables en cualquier nivel | boolean | false |
| emitPath | Si el valor devuelto incluye la ruta completa | boolean | true |
| multiple | Si es de selección múltiple | boolean | false |
| cascading | Si se vinculan en cascada | boolean | true |
| separator | Separador | string | '/' |
| collapseTags | Si se pliegan las etiquetas en el modo de selección múltiple | boolean | false |
| filterable | Si se puede buscar | boolean | false |
| itemConfig | Alias de los campos del nodo | [LhCascaderItemConfig](#type-LhCascaderItemConfig) | () => ({}) |
| sx | Props de disposición rápida (p. ej., { mt: 2, w: '50%' }); se convierten en estilos en línea aplicados al elemento raíz del disparador (el panel flotante no se ve afectado) | LhSxProps | — |
Events
| Evento | Descripción | Parámetros de la retrollamada |
|---|---|---|
| change | Se dispara cuando cambia el valor seleccionado | (value: (string | number)[], path: LhCascaderNode[] | null) |
| update:model-value | Se dispara cuando cambia el valor vinculado | value: (string | number)[] |
Estructura de datos
Definición del tipo LhCascaderNode:
interface LhCascaderNode {
value: string | number
label: string
disabled?: boolean
leaf?: boolean
children?: LhCascaderNode[]
}Definiciones de tipos
Las estructuras de tipos TypeScript exportadas por este componente (extraídas automáticamente de packages/components/cascader/src/types.ts y de las fuentes @lh-ui/share/core/*; abre cada entrada para ver la definición completa; la descripción de los atributos está en la tabla de Props de arriba):
LhCascaderProps
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
/** Props de disposición rápida */
sx?: LhSxProps
}LhCascaderItemConfig (de @lh-ui/share/core/cascader)
/**
* Mapeo del atributo item en las props de Cascader
*/
export interface LhCascaderItemConfig {
value?: string
label?: string
children?: string
disabled?: string
leaf?: string
}LhCascaderNode (de @lh-ui/share/core/cascader)
/**
* Nodo de Cascader
*/
export interface LhCascaderNode {
value: string | number
label: string
disabled?: boolean
leaf?: boolean
children?: LhCascaderNode[]
}LhComponentSize (de @lh-ui/share/core/shared)
export type LhComponentSize = (typeof LH_SIZE_CONST)[keyof typeof LH_SIZE_CONST]Slots
| Slot | Descripción | Contenido predeterminado |
|---|---|---|
| no-match | Contenido personalizado del panel de búsqueda cuando el filtro no encuentra coincidencias | Paquete de idioma cascader.noMatch |