Sortable.js с Vue 2.0 сортирует неправильно

#javascript #vue.js #vuejs2 #rubaxa-sortable

#javascript #vue.js #vuejs2 #rubaxa-сортируемый

Вопрос:

Я использую Sortable.js и Vue.js . Цель состоит в том, чтобы сортировать элементы и постоянно обновлять данные.

Он хорошо работал с Vue 1.x, но после обновления до версии 2.0 сортировка стала неверной. Массив по-прежнему обновляется корректно, но элементы в DOM находятся в неправильных местах.

 new Vue({
  el: '#app',
  template: '#sort',
  data: function() {
    return {
      items: [
        "http://placehold.it/200X300?text=image1",
        "http://placehold.it/200X300?text=image2",
        "http://placehold.it/200X300?text=image3",
        "http://placehold.it/200X300?text=image4"
      ],  
    }
  },
  mounted: function() {
    this.$nextTick(function () {
      Sortable.create(document.getElementById('sortable'), {
        animation: 200,
        onUpdate: this.reorder.bind(this),
      });
    })
  },
  methods: {
    reorder: function(event) {
        var oldIndex = event.oldIndex,
            newIndex = event.newIndex;
        this.items.splice(newIndex, 0, this.items.splice(oldIndex, 1)[0]);

    } 
   }
});
  

jsFiddle
https://jsfiddle.net/4bvtofdd/4 /

Может кто-нибудь мне помочь?

Комментарии:

1. Боюсь, что sortable сейчас несовместим с vue 2.0 из-за виртуального dom. Оба, похоже, имеют несовместимость при изменении DOM. Единственный возможный «патч», который я вижу, — это использовать 2 массива, 1 для рисования, а другой для отслеживания изменений

2. Ох. Думаю, тогда я должен использовать другой плагин: (

Ответ №1:

Сегодня у меня была похожая проблема.

Добавьте: значение ключа, чтобы убедиться, что Vue повторно отправляет элементы в правильном порядке после того, как сортировка изменяет порядок элементов

 <div v-for="item in items" :key="item.id">
  <!-- content -->
</div>
  

https://v2.vuejs.org/v2/guide/list.html#key

Ответ №2:

Как это бывает, Sortable отслеживает порядок в sortable.toArray() , поэтому довольно легко сделать вычисление, которое даст вам элементы в отсортированном порядке, в то время как исходный список элементов остается неизменным.

 new Vue({
  el: '#app',
  template: '#sort',
  data: {
    items: [
      "http://placehold.it/200X300?text=image1",
      "http://placehold.it/200X300?text=image2",
      "http://placehold.it/200X300?text=image3",
      "http://placehold.it/200X300?text=image4"
    ],
    order: null
  },
  computed: {
    sortedItems: function() {
      if (!this.order) {
      	return this.items;
      }
      return this.order.map((i) => this.items[i]);
    }
  },
  mounted: function() {
    this.$nextTick(() => {
      const sortable = Sortable.create(document.getElementById('sortable'), {
        animation: 200,
        onUpdate: () => { this.order = sortable.toArray(); }
      });
    })
  }
});  
 <script src="//cdnjs.cloudflare.com/ajax/libs/Sortable/1.4.2/Sortable.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="//unpkg.com/vue@2.0.1/dist/vue.js"></script>
<div id='app'></div>
<template id="sort">
  <div class="container">
    <div class="row sort-wrap" id="sortable">
      <div class="col-xs-6 col-md-3 thumbnail" v-for="(item, index) in items" :data-id="index">
        <img v-bind:src="item" alt="" class="img-responsive">
      </div>
    </div>
    <div v-for="item in sortedItems">
    {{item}}
    </div>
  </div>
</template>  

Ответ №3:

Убедитесь, что вы не используете prop, иначе вы не сможете выполнить сортировку. Если вы используете prop, назначьте данные prop атрибуту data и используйте вместо него атрибут data.