Vue
HTML
<div id="app">
<button @click="changePosition">
Change Position Of items
</button>
<list @item-position-changed="changeList" :list="list">
<template slot-scope={list}>
<list-item ref="item" v-for="item in list" :id="item.id" :key="item.id" :name="item.name">
</list-item>
</template>
</list>
</div>
CSS
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
Vue
Vue.component('list', {
template: '<div> changePositionQueue: {{changePositionQueue}} <br><br> <slot v-bind:list="sortedList"></slot></div>',
props: ['list'],
data() {
return {
changePositionQueue: [],
positionChangingProcess: false
}
},
watch: {
changePositionQueue(val) {
if (val) {
if (!this.positionChangingProcess)
this.startChangingPosition()
}
}
},
computed: {
sortedList() {
return this.list.sort( (item1, item2) => {return item1.position - item2.position} )
}
},
created() {
eventBus.$on('changePosition', this.pushToQueue);
},
methods: {
startChangingPosition() {
this.positionChangingProcess = true;
if (this.changePositionQueue.length === 0) {
this.positionChangingProcess = false;
return;
}
const item = this.changePositionQueue[0];
this.changePositionOfItem(item.id, item.position).then( ({list}) => {
this.$emit('item-position-changed', {list: list, callback: () => {
console.log('taking from queue')
this.changePositionQueue.shift();
this.startChangingPosition();
}})
})
},
pushToQueue(id, position) {
console.log('pushing to queue')
this.changePositionQueue.push({id: id, position: position});
},
changePositionOfItem(id, position) {
return new Promise((resolve) => {
let newList = JSON.parse(JSON.stringify(this.list));
const index = newList.findIndex( item => item.id === id);
newList[index].position = position;
resolve({list: newList})
})
}
}
})
Vue.component('list-item', {
template: '<div>{{name}}</div>',
props: ['id', 'name'],
methods: {
changePosition() {
eventBus.$emit('changePosition', this.id, Math.floor(Math.random() * 6) + 1 );
}
}
})
const eventBus = new Vue();
new Vue({
el: "#app",
data: {
list: [
{ id: 1, name: "first", position: 3 },
...