Vue.jsでドラッグ&ドロップを実装したい時はVue.Draggable安定。

公式

https://github.com/SortableJS/Vue.Draggable

デモサイト

https://sortablejs.github.io/Vue.Draggable/#/simple

Vue.Draggable

install

$ npm install vuedraggable

TypeScript対応

TypeScriptで普通に使おうとすると以下のようなエラーが出る。

JavaScriptの場合はやらなくてOK

Could not find a declaration file for module 'vuedraggable'. '/******/node_modules/vuedraggable/dist/vuedraggable.umd.min.js' implicitly has an 'any' type.
Try `npm install @types/vuedraggable` if it exists or add a new declaration (.d.ts) file containing `declare module 'vuedraggable';`

以下手順を実行することで解決。

d.tsファイルをsrc直下に作成。名前はなんでも良い。

$ touch types.d.ts

d.tsファイルに以下を記述。

declare module 'vuedraggable'

使い方

dataの配列をドラッグ&ドロップしたい場合、v-modelで渡すだけで良い。

<draggable v-model="myArray">
   <div v-for="element in myArray" :key="element.id">
     {{element.name}}
   </div>
</draggable>

Vuexを絡めて使う場合は、computedにget()/set()を定義して、ドラッグ&ドロップの結果がStoreに反映されるようにする。

<draggable v-model='myList'>
computed: {
    myList: {
        get() {
            return this.$store.state.myList
        },
        set(value) {
            this.$store.commit('updateList', value)
        }
    }
}

Type Scriptを使うため、Vue Property DecoratorやVue Class Componentなどを用いて書く場合は以下のような感じ。

export default class YourComponent extends Vue {  
	get myList () {
    return myModule.getAll()
  }

  set myList (items) {
    items.forEach((item, index) => {
      myModule.update(item)
    })
  }
}

ドラッグ&ドロップして出来た並び順を保存しておく技

setterの引数には、ドラッグ&ドロップで並び替えた後のリストが来る。

これを利用して、クラスにorderプロパティを持たせ、setterでindexを書き込むことで、並び順を保存しておくことができる。

export default class YourComponent extends Vue {  
	get myList () {
    return myModule.getAll().sort((a, b) => a.order - b.order)
  }

  set myList (items) {
    items.forEach((item, index) => {
      item.order = index
      myModule.update(item)
    })
  }
}

他にもアニメーションやネストなど色々できるので公式READMEは一読を推奨。