Vue быстро внедрить сортировку перетаскивания и падения на основе списка

Vue.js

предисловие

Сортировка списка перетаскиванием является относительно распространенным требованием в бизнесе.Обычные библиотеки перетаскивания JS включают Sortable.js, Vue.Draggable и т. д. Собственное событие перетаскивания HTML для сортировки перетаскиванием несложно в сочетании с Vue.transition-group

demo

API перетаскивания HTML5

draggableсобственностьtrue(Текст, картинки и ссылкиdraggableПо умолчаниюtrue)

<div draggable="true">能被拖放的元素</div>

событие перетаскивания

Перетаскивание включает два элемента: один — перетаскиваемый элемент (исходный объект), а другой — элемент зоны перетаскивания (целевой объект). Как показано на рисунке ниже, удерживайте элемент A и перетащите его к элементу B. Элемент A является исходным объектом, а элемент B — целевым объектом.

image-20201223092700804

Различные объекты имеют разные события перетаскивания.

триггерный объект название события иллюстрировать
исходный объект dragstart Запускается, когда исходный объект начинает перетаскиваться
drag Повторно срабатывает при перетаскивании исходного объекта
dragend В конце исходного объекта сопротивления
цель dragenter Запускается, когда исходный объект начинает входить в область действия целевого объекта
dragover Запускается, когда исходный объект перемещается в пределах границ целевого объекта.
dragleave Запускается, когда исходный объект покидает область действия целевого объекта.
drop Запускается, когда исходный объект освобождается в пределах области действия целевого объекта.

нужно знать, это:dragenterа такжеdragoverПоведение события по умолчанию заключается в отказе принять любой элемент, который был удален. Следовательно, мы должны использовать как в событиях перетаскивания, так и в событиях перетаскиванияpreventDefaultЧтобы предотвратить поведение браузера по умолчанию; и хотите стать целевым объектом, может отпустить область, вы должны установитьdragoverа такжеdrop

Перетащите и падение есть другие свойства и методы, но результаты, которые мы хотим достичь сегодня, нужно только иметь эти свойства, а методы, упомянутые выше, могут, если вы хотите включить, вы можете обратитьсяAPI перетаскивания HTML

Перетащите

Затем мы используем API перетаскивания для реализации сортировки списка перетаскиванием, а код основан на Vue.

Забудьте пока о сортировке анимаций. Код не сложный, поэтому я его весь выложил, а потом объяснил идею реализации:

  1. Поскольку перетаскивание происходит в реальном времени, оно не используется.dropвместо этого используетсяdragenterТриггерная сортировка.
  2. записать индекс исходного объекта, когда он начинает перетаскиватьсяdragIndexКогда он входит в целевой объект (соответствующийdragenterСобытие), вставьте его в расположение целевого объекта.
  3. вdragenterВ методе есть суждениеthis.dragIndex !== index(index — это индекс текущего целевого объекта), потому чтоdragenter

Окончательный эффект показан на следующем рисунке:

demo

<template>
  <ul class="list">
    <li
      @dragenter="dragenter($event, index)"
      @dragover="dragover($event, index)"
      @dragstart="dragstart(index)"
      draggable
      v-for="(item, index) in list"
      :key="item.label"
      class="list-item"
     >
      {{item.label}}
    </li>
  </ul>
</template>
<script>
export default {
  data() {
    return {
      list: [
        { label: '列表1' },
        { label: '列表2' },
        { label: '列表3' },
        { label: '列表4' },
        { label: '列表5' },
        { label: '列表6' },
      ],
      dragIndex: '',
      enterIndex: '',
    };
  },
  methods: {
    dragstart(index) {
      this.dragIndex = index;
    },
    dragenter(e, index) {
      e.preventDefault();
      // 避免源对象触发自身的dragenter事件
      if (this.dragIndex !== index) {
        const source = this.list[this.dragIndex];
        this.list.splice(this.dragIndex, 1);
        this.list.splice(index, 0, source);
        // 排序变化后目标对象的索引变成源对象的索引
        this.dragIndex = index;
      }
    },
    dragover(e, index) {
      e.preventDefault();
    },
  },
};
</script>
<style lang="scss" scoped>
.list {
  list-style: none;
  .list-item {
    cursor: move;
    width: 300px;
    background: #EA6E59;
    border-radius: 4px;
    color: #FFF;
    margin-bottom: 6px;
    height: 50px;
    line-height: 50px;
    text-align: center;
  }
}
</style>

Минус HTML и CSS, ядроdragenterС помощью не более 15 строк кода можно реализовать функцию сортировки методом перетаскивания. Конечно, этот эффект перетаскивания немного тупой, и ниже используется тот, который поставляется с Vue.transition-groupКомпонент, добавляющий плавные переходы в сортировку.

Сортировать анимацию

Если вы не знакомы с Vuetransition-groupПожалуйста, изучите VueСортировка перехода списков, которые здесь повторяться не будут.

Для облегчения сравнения с приведенным выше кодом, мы также выкладываем все коды одновременно, вы можете видеть, что изменения в коде невелики.ulэлемент меняется наtransition-group,существуетmethodsновое вshuffleметод добавления перехода в CSStransition: transform .3s;Сортировка может быть реализована в начале диаграммы эффекта сопротивления, показанной в первом.

вы можете нажатьэта ссылкаИметь онлайн-опыт.

<template>
  <div>
    <transition-group
      name="drag"
      class="list"
      tag="ul"
    >
      <li
        @dragenter="dragenter($event, index)"
        @dragover="dragover($event, index)"
        @dragstart="dragstart(index)"
        draggable
        v-for="(item, index) in list"
        :key="item.label"
        class="list-item">
        {{item.label}}
      </li>
    </transition-group>
  </div>
</template>
<script>
export default {
  data() {
    return {
      list: [
        { label: '列表1' },
        { label: '列表2' },
        { label: '列表3' },
        { label: '列表4' },
        { label: '列表5' },
        { label: '列表6' },
      ],
      dragIndex: '',
      enterIndex: '',
    };
  },
  methods: {
    shuffle() {
      this.list = this.$shuffle(this.list);
    },
    dragstart(index) {
      this.dragIndex = index;
    },
    dragenter(e, index) {
      e.preventDefault();
      // 避免源对象触发自身的dragenter事件
      if (this.dragIndex !== index) {
        const moving = this.list[this.dragIndex];
        this.list.splice(this.dragIndex, 1);
        this.list.splice(index, 0, moving);
        // 排序变化后目标对象的索引变成源对象的索引
        this.dragIndex = index;
      }
    },
    dragover(e, index) {
      e.preventDefault();
    },
  },
};
</script>
<style lang="scss" scoped>
.list {
  list-style: none;
  .drag-move {
    transition: transform .3s;
  }
  .list-item {
    cursor: move;
    width: 300px;
    background: #EA6E59;
    border-radius: 4px;
    color: #FFF;
    margin-bottom: 6px;
    height: 50px;
    line-height: 50px;
    text-align: center;
  }
}
</style>

Если вы хотите использовать собственный JS для реализации сортировки перетаскиванием и анимации перехода списков, вы можете обратиться к этой статье:JS DRAG Сортировка перетаскиванием