Drag and drop

Element Plus предоставляет гибкие средства для реализации функционала перетаскивания элементов (Drag and Drop) на основе компонентов ElTable, ElTree и ElDraggable (через интеграцию с vuedraggable). Основной принцип заключается в управлении состоянием данных, а не манипуляции DOM напрямую, что обеспечивает реактивность и предсказуемое поведение интерфейса.


Drag and Drop в таблицах (ElTable)

Компонент ElTable с возможностью перетаскивания строк требует подключения внешней библиотеки, например vuedraggable, для полноценной работы. Основные шаги:

  1. Импорт и подключение Draggable:
import draggable from 'vuedraggable';
  1. Обертка строк таблицы в Draggable:
<template>
  <el-table :data="tableData" style="width: 100%">
    <draggable v-model="tableData" tag="tbody">
      <el-table-column prop="name" label="Имя"></el-table-column>
      <el-table-column prop="age" label="Возраст"></el-table-column>
    </draggable>
  </el-table>
</template>

<script>
export default {
  data() {
    return {
      tableData: [
        { name: 'Иван', age: 28 },
        { name: 'Мария', age: 34 },
        { name: 'Пётр', age: 22 }
      ]
    };
  }
};
</script>

Ключевые моменты:

  • v-model связывает массив данных с компонентом Draggable. Перетаскивание автоматически обновляет порядок элементов в массиве.
  • tag="tbody" сохраняет структуру таблицы, предотвращая нарушение DOM.
  • Можно использовать события @start и @end для отслеживания начала и конца перетаскивания.

Drag and Drop в деревьях (ElTree)

Компонент ElTree поддерживает встроенный drag and drop через свойство draggable. Конфигурация включает обработку событий для контроля над перемещением узлов.

<template>
  <el-tree
    :data="treeData"
    :props="defaultProps"
    draggable
    @node-drag-start="handleDragStart"
    @node-drag-end="handleDragEnd"
    @node-drop="handleDrop"
  >
  </el-tree>
</template>

<script>
export default {
  data() {
    return {
      treeData: [
        { label: 'Фрукты', children: [{ label: 'Яблоко' }, { label: 'Банан' }] },
        { label: 'Овощи', children: [{ label: 'Морковь' }, { label: 'Картофель' }] }
      ],
      defaultProps: { children: 'children', label: 'label' }
    };
  },
  methods: {
    handleDragStart(node, event) {
      console.log('Начало перетаскивания', node);
    },
    handleDragEnd(node, event) {
      console.log('Конец перетаскивания', node);
    },
    handleDrop(draggingNode, dropNode, dropType, ev) {
      console.log('Перетащено', draggingNode, 'на', dropNode, 'тип', dropType);
    }
  }
};
</script>

Ключевые моменты:

  • draggable активирует возможность перетаскивания узлов.
  • dropType может быть 'before', 'after' или 'inner', что позволяет гибко управлять расположением элементов.
  • Обработка событий node-drag-start и node-drag-end позволяет реализовать кастомную логику (например, проверку условий перемещения или визуальные подсказки).

Настройка ограничений перетаскивания

Для предотвращения перемещения определённых элементов используются методы проверки и условия:

handleDrop(draggingNode, dropNode, dropType, ev) {
  if (dropNode.label === 'Запрещённая категория') {
    this.$message.warning('Перемещение запрещено');
    return false; // отменяет операцию
  }
}
  • Можно использовать allowDrop для более тонкого контроля на уровне ElTree.
  • Для таблиц можно фильтровать события @end, возвращая элементы в исходное состояние при нарушении условий.

Стилизация при перетаскивании

Element Plus автоматически применяет базовые стили для перетаскиваемых элементов, но их можно кастомизировать через CSS:

.draggable-chosen {
  background-color: #f0f9ff;
  border: 1px dashed #409eff;
}
.draggable-ghost {
  opacity: 0.6;
}
  • draggable-chosen — активный элемент во время перетаскивания.
  • draggable-ghost — элемент-заглушка, который следует за курсором.
  • Эти классы совместимы с vuedraggable и Element Plus.

Интеграция с Vuex и реактивностью

Чтобы изменения в порядке элементов сохранялись глобально, можно использовать Vuex или Pinia:

methods: {
  onDragEnd() {
    this.$store.commit('updateTableOrder', this.tableData);
  }
}
  • Важно, что v-model Draggable обеспечивает реактивное обновление массива.
  • Сохранение данных на сервере выполняется в обработчике @end или @node-drop, отправляя обновлённый порядок элементов через API.

Поддержка мобильных устройств

Для мобильного drag and drop рекомендуется использовать touch-совместимые версии vuedraggable или подключать библиотеку SortableJS с опцией forceFallback: true. Это обеспечивает плавное перетаскивание на сенсорных экранах без конфликтов с стандартными жестами.


Выводы по функциональности

  • Drag and Drop в Element Plus ориентирован на работу с данными, а не на прямую манипуляцию DOM.
  • ElTree поддерживает встроенные события и свойства для гибкой настройки.
  • Для ElTable требуется интеграция с vuedraggable, что позволяет сохранять порядок строк через реактивные массивы.
  • Настройка ограничений, кастомная стилизация и интеграция с хранилищами данных делают этот функционал мощным инструментом для сложных интерфейсов.