Привет, Хабр! Недавно я представил вам Vue DnD Kit — библиотеку для создания интерфейсов с перетаскиванием в Vue 3. Сегодня хочу рассказать о новом пакете vue-dnd-kit/components, который значительно упрощает разработку сложных drag & drop интерфейсов.
Важно: Эта публикация — краткая новость о выходе пакета компонентов. Для полноценных примеров и подробной документации рекомендую перейти на официальный сайт документации.
⚠️ Статус проекта: Пакет находится в активной разработке (бета-версия). API может изменяться между минорными версиями. Не рекомендуется для продакшена до версии 1.0.0.
Что такое vue-dnd-kit/components?
vue-dnd-kit/components — это пакет готовых компонентов, построенных поверх основного пакета vue-dnd-kit/core. Он предоставляет готовые решения для типовых сценариев использования drag & drop, таких как:
-
📋 Сортируемые таблицы с перетаскиванием строк и столбцов
-
📊 Канбан-доски для управления задачами
-
🌳 Древовидные структуры с неограниченной вложенностью
-
🧩 Интерактивные дашборды с перетаскиваемыми виджетами
Ключевые особенности
1. CLI для быстрой установки компонентов
Одна из самых крутых фич — встроенный CLI, который работает по принципу shadcn/ui:
# Посмотреть доступные компоненты pnpm dlx @vue-dnd-kit/components list # Добавить компонент в проект pnpm dlx @vue-dnd-kit/components add Table # Добавить компонент в конкретную папку pnpm dlx @vue-dnd-kit/components add Kanban --dir src/shared/components
Важно: CLI клонирует компоненты прямо в ваш проект, давая полный контроль над кодом и стилизацией. Вы можете свободно модифицировать, кастомизировать и адаптировать компоненты под свои нужды — это не зависимость, а ваш собственный код!
2. Минимальная стилизация
Все компоненты поставляются с минимальной стилизацией, что позволяет легко интегрировать их в любой дизайн-систему:
<template> <Table :rows="users" :columns="columns" > <template #caption>Список пользователей</template> <template #default="props"> <TableRow v-for="(user, index) in users" :key="user.id" :row="user" :row-index="index" v-bind="props" /> </template> </Table> </template> <style> /* Ваши собственные стили */ .vue-dnd-table { @apply w-full border-collapse; } .vue-dnd-table-row { @apply hover:bg-gray-50 transition-colors; } </style>
3. Гибкая система слотов
Каждый компонент предоставляет множество слотов для кастомизации:
<template> <Kanban :columns="columns" v-slot="{ columns }" > <KanbanColumn v-for="(column, index) in columns" :key="column.id" :column="column" :columns="columns" :column-index="index" :body-source="column.tasks" > <!-- Кастомный заголовок колонки --> <template #header> <div class="flex items-center gap-2"> <span class="font-semibold">{{ column.title }}</span> <span class="text-sm text-gray-500">({{ column.tasks.length }})</span> </div> </template> <!-- Кастомные карточки задач --> <KanbanItem v-for="(task, taskIndex) in column.tasks" :key="task.id" :item="task" :items="column.tasks" :item-index="taskIndex" > <div class="p-3 bg-white rounded-lg shadow-sm"> <h4 class="font-medium">{{ task.title }}</h4> <p class="text-sm text-gray-600 mt-1">{{ task.description }}</p> </div> </KanbanItem> <!-- Кастомный футер колонки --> <template #footer> <button class="w-full p-2 text-gray-500 hover:bg-gray-50 rounded"> + Добавить задачу </button> </template> </KanbanColumn> </Kanban> </template>
Доступные компоненты
📋 Table — Сортируемые таблицы
Полнофункциональная таблица с возможностью перетаскивания строк и столбцов:
<script setup lang="ts"> import { ref } from 'vue'; import { Table, TableRow, type ITableColumn } from './components/Table'; interface IUser { id: number; name: string; email: string; role: string; } const users = ref<IUser[]>([ { id: 1, name: 'Иван Петров', email: 'ivan@example.com', role: 'Админ' }, { id: 2, name: 'Мария Сидорова', email: 'maria@example.com', role: 'Менеджер', }, { id: 3, name: 'Алексей Козлов', email: 'alex@example.com', role: 'Разработчик', }, ]); const columns = ref<ITableColumn<IUser>[]>([ { label: 'ID', key: 'id' }, { label: 'Имя', key: 'name' }, { label: 'Email', key: 'email' }, { label: 'Роль', key: 'role' }, ]); </script> <template> <Table :rows="users" :columns="columns" > <template #caption>Список сотрудников</template> <template #default="props"> <TableRow v-for="(user, index) in users" :key="user.id" :row="user" :row-index="index" v-bind="props" /> </template> </Table> </template>
Особенности:
-
Перетаскивание строк для изменения порядка
-
Перетаскивание столбцов для изменения их позиции
-
Кастомные заголовки столбцов через слоты
-
Поддержка статусов (success, processing, failed)
-
Визуальные индикаторы при перетаскивании
📊 Kanban — Канбан-доски
Гибкая канбан-доска для управления задачами и проектами:
<script setup lang="ts"> import { ref } from 'vue'; import { Kanban, KanbanColumn, KanbanItem } from './components/Kanban'; interface ITask { id: number; title: string; description: string; priority: 'low' | 'medium' | 'high'; } interface IColumn { id: number; title: string; tasks: ITask[]; } const columns = ref<IColumn[]>([ { id: 1, title: 'К выполнению', tasks: [ { id: 1, title: 'Изучить документацию', description: 'Прочитать API docs', priority: 'medium', }, { id: 2, title: 'Написать тесты', description: 'Покрыть код тестами', priority: 'high', }, ], }, { id: 2, title: 'В работе', tasks: [ { id: 3, title: 'Разработать UI', description: 'Создать компоненты', priority: 'high', }, ], }, { id: 3, title: 'Готово', tasks: [ { id: 4, title: 'Настройка проекта', description: 'Инициализация репозитория', priority: 'low', }, ], }, ]); </script> <template> <Kanban :columns="columns" v-slot="{ columns }" > <KanbanColumn v-for="(column, index) in columns" :key="column.id" :column="column" :columns="columns" :column-index="index" :body-source="column.tasks" > <template #header> <div class="flex items-center justify-between"> <span class="font-semibold">{{ column.title }}</span> <span class="text-sm bg-gray-100 px-2 py-1 rounded-full"> {{ column.tasks.length }} </span> </div> </template> <KanbanItem v-for="(task, taskIndex) in column.tasks" :key="task.id" :item="task" :items="column.tasks" :item-index="taskIndex" > <div class="p-3 bg-white rounded-lg shadow-sm border-l-4" :class="{ 'border-red-500': task.priority === 'high', 'border-yellow-500': task.priority === 'medium', 'border-green-500': task.priority === 'low', }" > <h4 class="font-medium text-sm">{{ task.title }}</h4> <p class="text-xs text-gray-600 mt-1">{{ task.description }}</p> </div> </KanbanItem> </KanbanColumn> </Kanban> </template>
Особенности:
-
Перетаскивание задач между колонками
-
Перетаскивание колонок для изменения порядка
-
Кастомные заголовки и футеры колонок
-
Гибкая система слотов для кастомизации
🌳 Tree — Древовидные структуры
Иерархические структуры с неограниченной вложенностью:
<script setup lang="ts"> import { ref } from 'vue'; import { Tree } from './components/Tree'; interface IFile { id: number; name: string; type: 'file' | 'folder'; children?: IFile[]; } const files = ref<IFile[]>([ { id: 1, name: 'Проект', type: 'folder', children: [ { id: 2, name: 'src', type: 'folder', children: [ { id: 3, name: 'main.ts', type: 'file' }, { id: 4, name: 'App.vue', type: 'file' }, ], }, { id: 5, name: 'docs', type: 'folder', children: [{ id: 6, name: 'README.md', type: 'file' }], }, ], }, ]); </script> <template> <Tree :data="files" item-key="id" nesting-key="children" v-slot="{ item }" > <div class="flex items-center gap-2 py-1"> <span class="text-lg" :class="item.type === 'folder' ? 'text-blue-500' : 'text-gray-500'" > {{ item.type === 'folder' ? '📁' : '📄' }} </span> <span class="font-medium">{{ item.name }}</span> </div> </Tree> </template>
Особенности:
-
Неограниченная вложенность
-
Разворачивание/сворачивание узлов
-
Перетаскивание элементов между уровнями
-
Визуальные индикаторы для элементов с детьми
-
Подсветка зон для сброса
🧩 Dashboard — Интерактивные дашборды
Гибкая система виджетов с перетаскиванием:
<script setup lang="ts"> import { ref } from 'vue'; import { Dashboard, DashboardItem } from './components/Dashboard'; import ChartCard from './components/Dashboard/Example/ChartCard.vue'; import StatCard from './components/Dashboard/Example/StatCard.vue'; import TaskList from './components/Dashboard/Example/TaskList.vue'; interface IDashboardItem { id: number; component: Component; } const dashboard = ref<IDashboardItem[]>([ { id: 1, component: ChartCard }, { id: 2, component: TaskList }, { id: 3, component: StatCard }, ]); </script> <template> <Dashboard :data="dashboard" class="dashboard" > <TransitionGroup name="dashboard" appear > <DashboardItem v-for="(item, index) in dashboard" :key="item.id" :index="index" :source="dashboard" class="dashboard-item" > <component :is="item.component" /> </DashboardItem> </TransitionGroup> </Dashboard> </template> <style> .dashboard { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: auto auto; gap: 20px; padding: 20px; } .dashboard-item { border-radius: 12px; background: white; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); transition: all 0.3s ease; } .dashboard-move { transition: all 0.3s ease; } </style>
Особенности:
-
CSS Grid для адаптивной раскладки
-
Плавные анимации при перетаскивании
-
Поддержка TransitionGroup
-
Кастомные виджеты через слоты
Как начать использовать
Установка
# npm npm install @vue-dnd-kit/components @vue-dnd-kit/core # yarn yarn add @vue-dnd-kit/components @vue-dnd-kit/core # pnpm pnpm add @vue-dnd-kit/components @vue-dnd-kit/core
Быстрый старт с CLI
# Добавить таблицу pnpm dlx @vue-dnd-kit/components add Table # Добавить канбан-доску pnpm dlx @vue-dnd-kit/components add Kanban # Добавить дерево pnpm dlx @vue-dnd-kit/components add Tree # Добавить дашборд pnpm dlx @vue-dnd-kit/components add Dashboard
Подключение как плагин
import { createApp } from 'vue'; import App from './App.vue'; import VueDnDKitPlugin from '@vue-dnd-kit/core'; const app = createApp(App); app.use(VueDnDKitPlugin); app.mount('#app');
Преимущества перед другими решениями
1. Простота использования
-
CLI для быстрой установки компонентов
-
Интуитивный API на основе слотов
-
Минимальная конфигурация
2. Гибкость
-
Полный контроль над стилизацией
-
Кастомные слоты для любой кастомизации
-
Отсутствие привязки к конкретным UI-фреймворкам
3. Производительность
-
Оптимизированные компоненты
-
Минимальные перерисовки
-
Эффективная работа с большими списками
4. Доступность
-
Полная поддержка клавиатурной навигации
-
Совместимость со скринридерами
-
Семантическая разметка
Планы на будущее
Проект активно развивается! В разработке находятся дополнительные компоненты:
-
SortableList — простые сортируемые списки
-
FormBuilder — конструктор форм с перетаскиванием
-
Tabs — перетаскиваемые вкладки
-
FileExplorer — файловый менеджер
-
Grid — адаптивная сетка
Roadmap:
-
[x] Базовые drag & drop компоненты
-
[x] Table компонент
-
[x] Kanban доска
-
[x] Tree компонент
-
[ ] SortableList
-
[ ] FormBuilder
-
[ ] Dashboard
-
[ ] Tabs
-
[ ] FileExplorer
-
[ ] Grid
-
[ ] Тесты
-
[ ] Стабильный API (версия 1.0.0)
Заключение
vue-dnd-kit/components — это мощный инструмент для быстрой разработки сложных интерфейсов с перетаскиванием. Благодаря CLI, который работает по принципу shadcn/ui, гибкой системе слотов и минимальной стилизации, вы можете создавать профессиональные drag & drop интерфейсы за считанные минуты.
Ключевое преимущество: Компоненты клонируются в ваш проект, а не устанавливаются как зависимости. Это означает полную свободу в кастомизации и отсутствие привязки к конкретным версиям библиотеки.
Библиотека с открытым исходным кодом, активно развивается, и я буду рад любому вкладу от сообщества!
Полезные ссылки:
Буду рад вашим отзывам и предложениям в комментариях!
Теги: vue.js, drag-and-drop, dnd-kit, frontend-разработка, components, ui-library
Хабы: VueJS, Frontend-разработка
ссылка на оригинал статьи https://habr.com/ru/articles/920620/
Добавить комментарий