# Tableau

Tableau de données. Prend en charge le tri (contrôlé / non contrôlé), le filtrage par colonne, le redimensionnement des colonnes par glisser-déposer, les en-têtes multi-niveaux (imbrication illimitée via children) et les colonnes fixes ; définir height active le défilement virtuel (rowHeight doit alors correspondre à la hauteur réelle des lignes).

Tableau
<template>
  <div style="max-width: 760px">
    <p class="demo-note">size="small" + maxHeight + tri par défaut (defaultSortProp/defaultSortOrder) + filtre</p>
    <LhTable
      :data="rows"
      :columns="columns"
      size="small"
      stripe
      border
      :max-height="200"
      row-key="name"
      default-sort-prop="dynasty"
      default-sort-order="asc"
      :default-filtered-values="{ dynasty: ['Song'] }"
    >
      <template #price="{ value }">
        <span style="color: var(--lh-primary-color); font-weight: 600">{{ value }}</span>
      </template>
    </LhTable>
    <p class="demo-note">La colonne « Dynastie » est triée par défaut en ordre croissant et pré-filtrée sur « Song » ; le bouton de filtre de l'en-tête permet de modifier les critères.</p>
    <p class="demo-note" style="margin-top: 16px">En-têtes imbriquées (children) + élargissement par resizable + formatter + sorter personnalisé</p>
    <LhTable :data="rows2" :columns="groupColumns" border :height="180" :row-height="40" :sorter="dynastySorter">
      <template #price="{ value }">
        <span style="color: var(--lh-primary-color); font-weight: 600">{{ value }}</span>
      </template>
    </LhTable>
    <p class="demo-note">La colonne « Provenance » est mise en forme par formatter en « Collection impériale / Collection privée » ; la colonne « Estimation » est élargissable (resizable).</p>
  </div>
</template>

<script>
export default {
  data: () => ({
    rows: [
      { name: 'Voyageurs parmi les montagnes et les rivières', dynasty: 'Song', price: 1800 },
      { name: 'Séjour dans les monts Fuchun', dynasty: 'Yuan', price: 2600 },
      { name: 'Mille lieues de fleuves et de montagnes', dynasty: 'Song', price: 3200 },
      { name: 'Le long de la rivière lors de la fête Qingming', dynasty: 'Song', price: 1500 },
      { name: 'Le festin nocturne de Han Xizai', dynasty: 'Cinq dynasties', price: 2100 },
    ],
    rows2: [
      { name: 'Voyageurs parmi les montagnes et les rivières', dynasty: 'Song', provenance: 'impériale', price: 1800 },
      { name: 'Séjour dans les monts Fuchun', dynasty: 'Yuan', provenance: 'impériale', price: 2600 },
      { name: 'Le long de la rivière lors de la fête Qingming', dynasty: 'Song', provenance: 'impériale', price: 1500 },
      { name: 'Blanc lumineux la nuit', dynasty: 'Tang', provenance: 'privée', price: 980 },
    ],
    columns: [
      { prop: 'name', label: 'Œuvre', width: 160 },
      {
        prop: 'dynasty',
        label: 'Dynastie',
        width: 120,
        sortable: true,
        filters: [
          { text: 'Song', value: 'Song' },
          { text: 'Yuan', value: 'Yuan' },
          { text: 'Cinq dynasties', value: 'Cinq dynasties' },
        ],
      },
      { prop: 'price', label: 'Estimation (en dizaines de milliers)', width: 140, align: 'right', slot: 'price' },
    ],
    groupColumns: [
      {
        label: "Informations sur l'œuvre",
        children: [
          { prop: 'name', label: 'Œuvre', width: 150 },
          {
            prop: 'provenance',
            label: 'Provenance',
            width: 100,
            formatter: (r) => (r.provenance === 'impériale' ? 'Collection impériale' : 'Collection privée'),
          },
        ],
      },
      {
        label: 'Valorisation',
        children: [
          { prop: 'dynasty', label: 'Dynastie', width: 90, sortable: true },
          { prop: 'price', label: 'Estimation (en dizaines de milliers)', width: 130, align: 'right', resizable: true, slot: 'price' },
        ],
      },
    ],
  }),
  methods: {
    dynastySorter(a, b) {
      const order = ['Tang', 'Cinq dynasties', 'Song', 'Yuan']
      return order.indexOf(String(a.dynasty)) - order.indexOf(String(b.dynasty))
    },
  },
}
</script>

# Props

Prop Description Type Valeur par défaut
data Données des lignes LhTableRow[] []
columns Configuration des colonnes LhTableColumn[] []
height Hauteur du corps du tableau (la définition active le défilement virtuel ; un nombre correspond à des px) number \| string —
maxHeight Hauteur maximale en mode non virtuel number \| string —
rowHeight Hauteur des lignes pour le défilement virtuel (doit correspondre à la hauteur réelle) number —
stripe / border Rayures zébrées / bordures des cellules boolean false
size Taille 'small' \| 'default' \| 'large' 'default'
rowKey Nom du champ servant de clé de ligne string —
defaultSortProp / defaultSortOrder Colonne / direction du tri par défaut string / LhTableSortOrder —
sorter Fonction de tri personnalisée (a, b) => number —
resizable Active le redimensionnement des colonnes (nécessite également la configuration resizable au niveau de la colonne, qui doit avoir une width numérique) boolean false
defaultFilteredValues État de filtrage par défaut (non contrôlé, clé = prop de la colonne) Record<string, (string \| number)[]> —
filteredValues État de filtrage contrôlé (:filtered-values.sync) Record<string, (string \| number)[]> —
sx Propriétés de mise en page rapide — —

# Events

sortChange ({ prop, order }), filterChange ({ prop, values }), columnResize ({ prop, width }), update:filteredValues, rowClick (row, index)

# Slots

Slot Description
<nom de slot de colonne> Cellule personnalisée, paramètres de portée { row, column, index, value } (la colonne est désignée par column.slot)
empty Contenu en l'absence de données (par défaut : « 暂无数据 »)

# Accessibilité

La ligne d'en-tête est role="row" avec aria-sort sur les colonnes triables, les lignes du corps sont role="row" ; le panneau de filtre est role="menu", la poignée de redimensionnement porte un aria-label et un tabindex, et permet un ajustement au clavier vers la gauche / la droite.

Copyright © 2024-2026 FengMo WenXue