Vue Draggable представление не синхронизировано с моделью

Я работаю над некоторыми функциями перетаскивания и по какой-то причине мой взгляд, кажется, не синхронизирован с моей моделью. Для некоторых элементов в моем списке я бы хотел, чтобы они не перетаскивались и оставались на своих заданных позициях. Когда я пытаюсь переместить перетаскиваемый предмет впереди другого, то мои не перетаскиваемые предметы затем перемещаются с позиции. Я создал JSFiddle, чтобы помочь объяснить здесь https://jsfiddle.net/2tyqjppq/8/. Сценарий использования перемещает значение C впереди B, и ожидаемый порядок - это A Z C B, но фактическое значение A B Z C. Следует отметить, что я имею в виду привязку к вычисляемому свойству, а не к модели специально для случая, когда перетаскивание + падение недействительно, это облегчает возврат.

Данные

myArray: [
    {'name': 'A'},
    {'name': 'Z'},
    {'name': 'B'},
    {'name': 'C'}
  ]

Перетаскиваемый

 <draggable class="warp-div" :list="getElements" :options="{group:'people', draggable:'.element-draggable'}"
@change="onChange">
  <div class="div" :class="[element.name === 'A' || element.name === 'Z' ? '' : 'element-draggable']" :style="'background-color:'+element.color" v-for="element in myArray">{{element.name}}</div>
</draggable>

Компьютерная собственность

getElements () {
  console.log('getting list elements');
  console.log(this.myArray);
  const temp = this.myArray.map(t => t);
  return temp;
}

Способ обновления модели

onChange (event) {
    if (event.moved) {
    const element = event.moved.element;
    console.log(element.name);

    // +2 to insert into myArray[2] as non draggable items are in spots 0,1
    const indexToInsert = event.moved.newIndex + 2;
    console.log(indexToInsert);

    //remove element from model
    for (let i = 0; i < this.myArray.length; i++) {
        if (this.myArray[i].name === element.name) {
        this.myArray.splice(i, 1);
      }
    }

    // insert element into proper place
    this.myArray.splice(indexToInsert, 0, element);
    console.log('Finished onChange');
    console.log(this.myArray);
  }
}

1 ответ

Самое близкое к этому достижение - отменить ход (см. Как отменить перетаскивание).

Это не дает вам точно такой же UX, так как не перетаскиваемые элементы начинают перетаскивать, но они не завершают перемещение.

шаблон

<draggable class="warp-div" 
  :list="myArray" 
  :options="{group:'alphabet', draggable:'.div'}" 
  :move="onMoveCallback">

составная часть

methods: {
  onMoveCallback: function(evt, originalEvent) {
    return evt.dragged.classList.contains('element-draggable');
  },

JSFiddle


Смешанные индексы

Когда список частично перетаскиваемый (т.е. только некоторые элементы имеют перетаскиваемый класс), внутренний список Sortable отличается от списка Vue.

Вы можете увидеть это, нажав на @sort="onSort" event - event.oldIndex и event.newIndex отражают позиции в подсписке элементов с классом.element-draggable, то есть элементов "B" и "C".

@change="onChange" Метод получает версию Vue oldIndex, но сортируемую версию newIndex. Отображение обновляется до запуска onChange (смотрите, что $emit находится в $nextTick), поэтому использование этого хука не выглядит жизнеспособным.

vuedraggable.js

onDragUpdate(evt) {
  removeNode(evt.item)
  insertNodeAt(evt.from, evt.item, evt.oldIndex)
  const oldIndex = this.context.index
  const newIndex = this.getVmIndex(evt.newIndex)
  this.updatePosition(oldIndex, newIndex)
  const moved = { element: this.context.element, oldIndex, newIndex }
  this.emitChanges({ moved })
},

...

emitChanges(evt) {
  this.$nextTick(() => {
    this.$emit('change', evt)
  });
},
Другие вопросы по тегам