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');
},
Смешанные индексы
Когда список частично перетаскиваемый (т.е. только некоторые элементы имеют перетаскиваемый класс), внутренний список 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)
});
},