Skip to content

STable

Таблица.

В чем отличие от аналогов?

В отличие от популярных библиотек компонентов для Vue3:

  1. Семантика поддерживает и итератор строк-значений, и просто вставку строк как есть.
  2. Позволяет задать состояние, когда нет данных, одним атрибутом.
  3. Позволяет сделать горизонтальный скролл сверху таблицы, что полезно для длинных таблиц с большим кол-вом колонок.

Базовый пример

ПользовательТарифБалансРольДата регистрации
IvanovБазовый3000customer2025-11-04
StepanovБазовый4500customer2025-11-05
PetrovБазовый1716customer2025-11-05
ИТОГО9216
<STable :data="users">
    <template #header>
        <td>Пользователь</td>
        <td>Тариф</td>
        <td>Баланс</td>
        <td>Роль</td>
        <td>Дата регистрации</td>
        <td></td>
    </template>
    <template #row="{ row }">
        <td>{{ row.username }}</td>
        <td>{{ row.plan }}</td>
        <td>{{ row.balance }}</td>
        <td>{{ row.role }}</td>
        <td>{{ row.created_at }}</td>
        <td>
            <SActionIcon title="Удалить" :confirm="`Вы действительно хотите удалить пользователя «${row.username}»?`"
                @click="deleteUser(row.username)" icon="trash" danger />
        </td>
    </template>
    <template #footer>
        <td>ИТОГО</td>
        <td></td>
        <td>{{ totalBalance }}</td>
        <td></td>
        <td></td>
        <td></td>
    </template>
</STable>

Утилиты выравнивания

По умолчанию ячейки выравниваются по позиции колонки: первая — по левому краю, последняя — по правому, остальные — по центру (одинаково для ячеек <td> и заголовков <th>). Выравнивание конкретной ячейки можно переопределить классами на <td>/<th>.left, .center, .right, а .nowrap запрещает перенос строки:

ТоварЦенаОстатокАртикул
Кофемолка3 200 ₽12KF-001-XL
Чайник1 850 ₽4CH-204
<STable :data="rows">
    <template #header>
        <td>Товар</td>
        <td class="right">Цена</td>
        <td class="left">Остаток</td>
        <td class="nowrap">Артикул</td>
    </template>
    <template #row="{ row }">
        <td>{{ row.name }}</td>
        <td class="right">{{ row.price }}</td>
        <td class="left">{{ row.stock }}</td>
        <td class="nowrap">{{ row.sku }}</td>
    </template>
</STable>

Подсветка строк при наведении

Для подсветки при наведении добавляем атрибут hoverable

ПользовательТарифБалансРольДата регистрации
IvanovБазовый3000customer2025-11-04
StepanovБазовый4500customer2025-11-05
PetrovБазовый1716customer2025-11-05
ИТОГО9216
<STable :data="users" hoverable>
    ...
</STable>

Явные границы по краям ячеек

Для отрисовки границ добавляем атрибут bordered

ПользовательТарифБалансРольДата регистрации
IvanovБазовый3000customer2025-11-04
StepanovБазовый4500customer2025-11-05
PetrovБазовый1716customer2025-11-05
ИТОГО9216
<STable :data="users" bordered>
    ...
</STable>

Выделение четных строк

Для выделения четных строк добавляем атрибут striped

ПользовательТарифБалансРольДата регистрации
IvanovБазовый3000customer2025-11-04
StepanovБазовый4500customer2025-11-05
PetrovБазовый1716customer2025-11-05
SidorovБазовый6000customer2025-11-06
ИТОГО15216
<STable :data="users" striped>
    ...
</STable>

Компактные ячейки

По умолчанию у ячеек комфортные отступы. Для плотных таблиц с большим количеством данных можно уменьшить отступы атрибутом compact.

ПользовательТарифБалансРольДата регистрации
IvanovБазовый3000customer2025-11-04
StepanovБазовый4500customer2025-11-05
PetrovБазовый1716customer2025-11-05
ИТОГО9216
<STable :data="users" compact>
    ...
</STable>

Фиксированная шапка

Чтобы зафиксировать шапку, устанавливаем высоту таблицы в атрибуте height.

ПользовательИмяФамилияДата рожденияРостВесТарифБалансРольДата регистрации
IvanovИванИванов1995.06.0617580Базовый3000Пользователь2025-11-04
StepanovСтепанСтепанов1990.02.1418288-4500Админ2025-11-05
PetrovПетрПетров1988.09.2117876Премиум1716Пользователь2025-11-05
SidorovСергейСидоров1993.12.0117072Базовый6000Пользователь2025-11-06
AlexeevАлексейАлексеев1996.03.3018590-2000Редактор2025-11-09
Ivanov2ИванИванов1995.06.0617580Базовый3000Пользователь2025-11-04
Stepanov2СтепанСтепанов1990.02.1418288-4500Админ2025-11-05
Petrov2ПетрПетров1988.09.2117876Премиум1716Пользователь2025-11-05
Sidorov2СергейСидоров1993.12.0117072Базовый6000Пользователь2025-11-06
Alexeev2АлексейАлексеев1996.03.3018590-2000Редактор2025-11-09
ИТОГО34432
<STable :data="users" height="300px">
    ...
</STable>
Для высоты таблицы с фиксированной шапкой удобно использовать 80vh, чтобы таблица занимала 80% от высоты экрана.

Горизонтальный скролл сверху

ПользовательИмяФамилияДата рожденияРостВесТарифБалансРольДата регистрации
IvanovИванИванов1995.06.0617580Базовый3000Пользователь2025-11-04
StepanovСтепанСтепанов1990.02.1418288-4500Админ2025-11-05
PetrovПетрПетров1988.09.2117876Премиум1716Пользователь2025-11-05
SidorovСергейСидоров1993.12.0117072Базовый6000Пользователь2025-11-06
AlexeevАлексейАлексеев1996.03.3018590-2000Редактор2025-11-09
ИТОГО17216
<STable :data="users" top-scroll>
    ...
</STable>

Кастомный контент внутри tbody

Если нужно задать явные строки в tbody вместо перебора #row, то используем дефолтный слот (в нем для отдельных строк нужно явно указать <tr>).

ПользовательТарифБалансРольДата регистрации
IvanovБазовый3000customer2025-11-04
StepanovБазовый4500customer2025-11-05
PetrovБазовый1716customer2025-11-05
ИТОГО9216
<STable>
    <template #header>
        <td>Пользователь</td>
        <td>Тариф</td>
        <td>Баланс</td>
        <td>Роль</td>
        <td>Дата регистрации</td>
        <td></td>
    </template>
    <tr v-for="user in users" :key="user.username">
        <td>{{ user.username }}</td>
        <td>{{ user.plan }}</td>
        <td>{{ user.balance }}</td>
        <td>{{ user.role }}</td>
        <td>{{ user.created_at }}</td>
        <td>
            <SActionIcon title="Удалить" :confirm="`Вы действительно хотите удалить пользователя «${user.username}»?`"
                @click="deleteUser(user.username)" icon="trash" danger />
        </td>
    </tr>
    <template #footer>
        <td>ИТОГО</td>
        <td></td>
        <td>{{ totalBalance }}</td>
        <td></td>
        <td></td>
        <td></td>
    </template>
</STable>

Если это нужно, просто используем отдельные слоты headers / footers (добавляется в конце "s"), в которые уже добавляем <tr>.

vue
<template>
<STable>
    <template #headers>
        <tr><td>...</td></tr>
        <tr><td>...</td></tr>
    </template>
    ...
    <template #footers>
        <tr><td>...</td></tr>
        <tr><td>...</td></tr>
    </template>
</STable>
</template>

Сообщение о том, что нет данных

Когда задаем data и перебираем его через <template #row>, то часто (например, когда есть фильтры страницы) бывает нужно показать состояние «Ничего не найдено», когда в data ноль строк. По умолчанию в таком случае выводится сообщение «Ничего не найдено», которое можно заменить на кастомное через пропс/слот nodata:

ПользовательТарифБалансРольДата регистрации
Пользователи не найдены
ИТОГО
<STable :data="users" nodata="Пользователи не найдены">
    ...
</STable>

или

ПользовательТарифБалансРольДата регистрации
По заданным критериям поиска ничего не нашлось
ИТОГО
<STable :data="users">
    <template #nodata>
        <SNote>По заданным критериям поиска ничего не нашлось</SNote>
    </template>
    ...
</STable>

Интерфейс компонента

Свойства (Props)

НазваниеТипПо умолчаниюОписание
dataT[] | Record<string | number, T>undefinedМассив или объект данных для итерации (используется вместе со слотом #row).
hoverablebooleanfalseПодсветка строки при наведении курсора.
stripedbooleanfalseЧередование цвета фона строк (выделение четных строк).
borderedbooleanfalseОтрисовка границ (бордеров) у всех ячеек.
compactbooleanfalseУменьшенные отступы в ячейках для плотных таблиц.
nodatastring'Ничего не найдено'Текст, выводимый, когда data пустое.
fixedHeaderbooleanfalseФиксированная шапка (принудительно), если не задана height.
heightstringundefinedФиксированная высота таблицы (например, 300px или 80vh). Автоматически включает fixedHeader.
topScrollbooleanfalseПереносит горизонтальный скролл наверх таблицы.

Слоты (Slots)

НазваниеОписание
headerСодержимое <tr/> внутри <thead>. Подходит для большинства таблиц (без rowspan/colspan в шапке).
headersПолный контроль над <thead> (вместо header). Нужно явно писать теги <tr>.
rowСлот с областью видимости { row, index }. Отрисовывается для каждого элемента из data. Внутри нужно писать только <td>.
defaultПереопределяет содержимое <tbody>. Используется, если не передан data. Нужно явно писать теги <tr>.
footerСодержимое <tr/> внутри <tfoot>.
footersПолный контроль над <tfoot> (содержит теги <tr>).
nodataКастомный HTML для пустого состояния, заменяет пропс nodata.