Skip to content
API 风格:

Arborescence ​

La conversion de données aplaties en arbre ainsi que la propagation de la coche sont implémentées dans des fonctions pures de la couche core ; le composant ne gère que le rendu et le clavier.

Utilisation de base ​

Utilisation de base
Frontend
Vue
React
Exploitation
vue
<script setup>
import { ref } from 'vue'
const treeData = [
  { key: 'a', label: 'Frontend', children: [
    { key: 'a-1', label: 'Vue' },
    { key: 'a-2', label: 'React' },
  ] },
  { key: 'b', label: 'Backend', children: [{ key: 'b-1', label: 'Node' }] },
  { key: 'c', label: 'Exploitation', disabled: true },
]
</script>

<template>
  <!-- Utilisation de base -->
  <LhTree :data="treeData" :default-expanded-keys="['a']" />
</template>
vue
<script>
export default {
  data() {
    return {
      treeData: [
        { key: 'a', label: 'Frontend', children: [
          { key: 'a-1', label: 'Vue' },
          { key: 'a-2', label: 'React' },
        ] },
        { key: 'b', label: 'Backend', children: [{ key: 'b-1', label: 'Node' }] },
        { key: 'c', label: 'Exploitation', disabled: true },
      ],
    }
  },
}
</script>

<template>
  <!-- Utilisation de base -->
  <LhTree :data="treeData" :default-expanded-keys="['a']" />
</template>

Coche en cascade ​

Cocher un parent cascade sur tous ses descendants ; lorsque tous les enfants sont cochés, le parent est automatiquement coché, et une sélection partielle affiche l'état intermédiaire (indeterminate).

Coche en cascade
Frontend
Vue
React
Backend
Node
Exploitation
vue
<script setup lang="ts">
const treeData = [
  { key: 'a', label: 'Frontend', children: [
    { key: 'a-1', label: 'Vue' },
    { key: 'a-2', label: 'React' },
  ] },
  { key: 'b', label: 'Backend', children: [{ key: 'b-1', label: 'Node' }] },
  { key: 'c', label: 'Exploitation', disabled: true },
]
</script>

<template>
  <!-- Coche en cascade -->
  <LhTree :data="treeData" show-checkbox :default-expanded-keys="['a', 'b']" />
</template>
vue
<script>
export default {
  data() {
    return {
      treeData: [
        { key: 'a', label: 'Frontend', children: [
          { key: 'a-1', label: 'Vue' },
          { key: 'a-2', label: 'React' },
        ] },
        { key: 'b', label: 'Backend', children: [{ key: 'b-1', label: 'Node' }] },
        { key: 'c', label: 'Exploitation', disabled: true },
      ],
    }
  },
}
</script>

<template>
  <!-- Coche en cascade -->
  <LhTree :data="treeData" show-checkbox :default-expanded-keys="['a', 'b']" />
</template>

Chargement paresseux ​

Avec lazy activé, l'expansion d'un nœud non chargé appelle le rappel load (resolve soumet les nœuds enfants et déclenche l'expansion, reject l'annule) ; la flèche affiche un état de rotation pendant le chargement. Un nœud chargeable doit déclarer explicitement isLeaf: false (sinon un nœud sans children est déduit comme feuille et n'affiche pas de flèche d'expansion) ; les nœuds enfants chargés qui sont encore des branches en attente de chargement doivent également déclarer isLeaf: false, tandis que les vraies feuilles déclarent isLeaf: true.

Chargement paresseux
vue
<script setup>
import { ref } from 'vue'

const lazyData = ref([
  { key: 'lazy', label: 'Cliquer pour charger', isLeaf: false },
])

function loadNodes(node, resolve, reject) {
  // Simulation d'une requête asynchrone
  setTimeout(() => {
    if (node.key === 'lazy') {
      resolve([
        { key: 'lazy-1', label: 'Nœud enfant 1', isLeaf: true },
        { key: 'lazy-2', label: 'Nœud enfant 2', isLeaf: true },
      ])
    } else {
      reject(new Error('nothing to load'))
    }
  }, 600)
}
</script>

<template>
  <!-- Chargement paresseux -->
  <LhTree :data="lazyData" lazy :load="loadNodes" />
</template>
vue
<script>
export default {
  data() {
    return {
      lazyData: [{ key: 'lazy', label: 'Cliquer pour charger', isLeaf: false }],
    }
  },
  methods: {
    // Simulation d'une requête asynchrone
    loadNodes(node, resolve, reject) {
      setTimeout(() => {
        if (node.key === 'lazy') {
          resolve([
            { key: 'lazy-1', label: 'Nœud enfant 1', isLeaf: true },
            { key: 'lazy-2', label: 'Nœud enfant 2', isLeaf: true },
          ])
        } else {
          reject(new Error('nothing to load'))
        }
      }, 600)
    },
  },
}
</script>

<template>
  <!-- Chargement paresseux -->
  <LhTree :data="lazyData" lazy :load="loadNodes" />
</template>

Sans cascade parent-enfant (checkStrictly) ​

Avec checkStrictly activé, la coche ne s'applique qu'au nœud lui-même : pas de cascade vers les descendants, pas de remontée vers les ancêtres, et pas d'état intermédiaire.

checkStrictly
Frontend
Vue
React
Backend
Node
Exploitation
vue
<script setup lang="ts">
const treeData = [
  { key: 'a', label: 'Frontend', children: [
    { key: 'a-1', label: 'Vue' },
    { key: 'a-2', label: 'React' },
  ] },
  { key: 'b', label: 'Backend', children: [{ key: 'b-1', label: 'Node' }] },
  { key: 'c', label: 'Exploitation', disabled: true },
]
</script>

<template>
  <!-- Sans cascade parent-enfant -->
  <LhTree :data="treeData" show-checkbox check-strictly :default-expanded-keys="['a', 'b']" />
</template>
vue
<script>
export default {
  data() {
    return {
      treeData: [
        { key: 'a', label: 'Frontend', children: [
          { key: 'a-1', label: 'Vue' },
          { key: 'a-2', label: 'React' },
        ] },
        { key: 'b', label: 'Backend', children: [{ key: 'b-1', label: 'Node' }] },
        { key: 'c', label: 'Exploitation', disabled: true },
      ],
    }
  },
}
</script>

<template>
  <!-- Sans cascade parent-enfant -->
  <LhTree :data="treeData" show-checkbox check-strictly :default-expanded-keys="['a', 'b']" />
</template>

Sélection et clés contrôlées ​

multiple autorise la sélection multiple ; expand-on-click-node étend ou réduit l'arbre au clic sur un nœud ; default-selected-keys / v-model:selected-keys contrôlent la sélection ; default-checked-keys / v-model:checked-keys contrôlent la coche ; default-expanded-keys / v-model:expanded-keys contrôlent l'expansion ; disabled désactive l'arbre entier.

Sélection et coche contrôlées
Design
Couleurs
Polices
Ingénierie

Sélection : [ "x" ] | Coche : [ "x-1" ]

Arbre entièrement désactivé
Ingénierie
vue
<script setup>
import { ref } from 'vue'
const selKeys = ref(['x'])
const chkKeys = ref(['x-1'])
const ctrlData = [
  { key: 'x', label: 'Design', children: [
    { key: 'x-1', label: 'Couleurs' },
    { key: 'x-2', label: 'Polices' },
  ] },
  { key: 'y', label: 'Ingénierie' },
]
</script>

<template>
  <!-- Sélection et coche contrôlées -->
  <LhTree
    v-model:selected-keys="selKeys"
    v-model:checked-keys="chkKeys"
    :data="ctrlData"
    multiple
    expand-on-click-node
    :default-expanded-keys="['x']"
    :default-selected-keys="['x']"
    :default-checked-keys="['x-1']"
  />
  <p class="demo-tree-log">Sélection : {{ selKeys }} | Coche : {{ chkKeys }}</p>
  <!-- Arbre entièrement désactivé -->
  <LhTree :data="ctrlData" disabled />
</template>
vue
<script>
export default {
  data() {
    return {
      selKeys: ['x'],
      chkKeys: ['x-1'],
      ctrlData: [
        { key: 'x', label: 'Design', children: [
          { key: 'x-1', label: 'Couleurs' },
          { key: 'x-2', label: 'Polices' },
        ] },
        { key: 'y', label: 'Ingénierie' },
      ],
    }
  },
}
</script>

<template>
  <!-- Sélection et coche contrôlées -->
  <LhTree
    v-model:selected-keys="selKeys"
    v-model:checked-keys="chkKeys"
    :data="ctrlData"
    multiple
    expand-on-click-node
    :default-expanded-keys="['x']"
    :default-selected-keys="['x']"
    :default-checked-keys="['x-1']"
  />
  <p class="demo-tree-log">Sélection : {{ selKeys }} | Coche : {{ chkKeys }}</p>
  <!-- Arbre entièrement désactivé -->
  <LhTree :data="ctrlData" disabled />
</template>

API ​

LhTree Props ​

PropDescriptionTypeValeur par défaut
dataDonnées de l'arbre[LhTreeNode](#type-LhTreeNode)[]—
showCheckboxAffiche les cases à cocherbooleanfalse
multipleSélection multiple (le clic sur un nœud bascule la sélection au lieu de la remplacer)booleanfalse
expandOnClickNodeÉtend ou réduit au clic sur un nœud non feuillebooleantrue
defaultExpandedKeysClés étendues par défaut (non contrôlées)string[]() => []
expandedKeysClés étendues contrôléesstring[]—
defaultSelectedKeysClés sélectionnées par défaut (non contrôlées)string[]() => []
selectedKeysClés sélectionnées contrôléesstring[]—
defaultCheckedKeysClés cochées par défaut (non contrôlées)string[]() => []
checkedKeysClés cochées contrôléesstring[]—
checkStrictlyCoche sans cascade parent-enfant (la coche ne s'applique qu'au nœud lui-même, pas de cascade ni d'état intermédiaire)booleanfalse
lazyMode de chargement paresseux (appelle load lors de l'expansion d'un nœud non chargé)booleanfalse
loadRappel de chargement paresseux (resolve soumet les nœuds enfants et déclenche l'expansion, reject annule)(node: LhTreeNode, resolve: (children: LhTreeNode[]) => void, reject: (reason?: unknown) => void) => void—
disabledDésactivé globalementbooleanfalse
sxPropriétés de mise en page rapide sxLhSxProps—

Events ​

ÉvénementDescriptionParamètre de rappel
update:expandedKeysÉmis lorsque la liste des clés étendues change, à utiliser avec v-model:expanded-keys(keys: string[])
update:selectedKeysÉmis lorsque la liste des clés sélectionnées change, à utiliser avec v-model:selected-keys(keys: string[])
update:checkedKeysÉmis lorsque la liste des clés cochées change, à utiliser avec v-model:checked-keys(keys: string[])
selectÉmis après la sélection ou la bascule de sélection d'un nœud au clic(key: string, node: LhTreeNode)
checkÉmis après un changement de coche(keys: string[], node: LhTreeNode)
expandÉmis après l'expansion ou la réduction d'un nœud(key: string, expanded: boolean)
nodeLoadÉmis après le retour des nœuds enfants en chargement paresseux(node: LhTreeNode, children: LhTreeNode[])

Slots : node (portée { node, level, expanded, selected }), empty.

LhTreeNode ​

ChampDescriptionType
keyClé uniquestring
labelTexte affichéstring
childrenNœuds enfantsLhTreeNode[]
disabledDésactivéboolean
isLeafFeuille ou non (déduit des children lorsque non renseigné)boolean

Accessibilité ​

  • role="tree" + role="treeitem", aria-level / aria-expanded / aria-selected / aria-disabled tous exposés
  • Case à cocher role="checkbox" + aria-checked (l'état intermédiaire vaut mixed)
  • Clavier (pattern tree des APG) : ↑/↓ pour passer d'un élément à l'autre (en sautant les désactivés, en bouclant), → pour étendre ou entrer dans le premier enfant, ← pour réduire ou remonter au parent, Home/End pour le premier et le dernier, Enter/Space pour activer ; roving tabindex

Définitions de types ​

Les structures de types TypeScript exportées par ce composant sont les suivantes (extraites automatiquement de packages/components/tree/src/types.ts et de @lh-ui/share/core/* ; cliquez sur chaque entrée pour afficher la définition complète ; les descriptions des props se trouvent dans le tableau Props ci-dessus) :

LhTreeProps
ts
export interface LhTreeProps {
  /** Données de l'arbre */
  data: LhTreeNode[]
  /** Affiche les cases à cocher */
  showCheckbox?: boolean
  /** Sélection multiple (le clic sur un nœud bascule la sélection au lieu de la remplacer) */
  multiple?: boolean
  /** Étend ou réduit au clic sur un nœud non feuille */
  expandOnClickNode?: boolean
  /** Clés étendues par défaut (non contrôlées) */
  defaultExpandedKeys?: string[]
  /** Clés étendues contrôlées */
  expandedKeys?: string[]
  /** Clés sélectionnées par défaut (non contrôlées) */
  defaultSelectedKeys?: string[]
  /** Clés sélectionnées contrôlées */
  selectedKeys?: string[]
  /** Clés cochées par défaut (non contrôlées) */
  defaultCheckedKeys?: string[]
  /** Clés cochées contrôlées */
  checkedKeys?: string[]
  /** Coche sans cascade parent-enfant (la coche ne s'applique qu'au nœud lui-même, pas de cascade ni d'état intermédiaire) */
  checkStrictly?: boolean
  /** Mode de chargement paresseux : appelle load lors de l'expansion d'un nœud non feuille non chargé */
  lazy?: boolean
  /** Rappel de chargement paresseux : resolve soumet les nœuds enfants et déclenche l'expansion, reject (ou une erreur) annule */
  load?: (
    node: LhTreeNode,
    resolve: (children: LhTreeNode[]) => void,
    reject: (reason?: unknown) => void,
  ) => void
  /** Désactivé globalement */
  disabled?: boolean
  /** Propriétés de mise en page rapide sx */
  sx?: LhSxProps
}
LhFlatTreeNode (provenant de @lh-ui/share/core/tree)
ts
/** Nœud aplati (pour le rendu) */
export interface LhFlatTreeNode {
  node: LhTreeNode
  key: string
  level: number
  parentKey: string | null
  /** Chaîne des ancêtres (elle-même non comprise) */
  ancestorKeys: string[]
  /** Feuille ou non */
  isLeaf: boolean
}
LhTreeNode (provenant de @lh-ui/share/core/tree)
ts
/** Données d'un nœud de l'arbre */
export interface LhTreeNode {
  /** Clé unique */
  key: string
  /** Texte affiché */
  label: string
  /** Nœuds enfants */
  children?: LhTreeNode[]
  /** Désactivé */
  disabled?: boolean
  /** Feuille ou non (déduit des children lorsque non renseigné) */
  isLeaf?: boolean
}
LhTreeCheckState (provenant de @lh-ui/share/core/tree)
ts
/** État de la coche */
export type LhTreeCheckState = 'checked' | 'indeterminate' | 'unchecked'

La beauté de la tradition, la fondation du code