こんにちは。Vue.js勉強中の者です。
ドラッグアンドドロップでリストを並び替えて色々したいって時あるじゃないですか。
しかも入れ子のリストで、子が親を飛び越えたりせずに同じ階層同士でしか並び替えしたくないって時もあるじゃないですか。あるか?
jQueryUIでも頑張れば出来そうですが、Vue.js導入してVue.Draggableを使えばアホ簡単に出来たのでその備忘録です。
Vue.Draggable
ドラッグアンドドロップで並び替えすることをうまいことやってくれるプラグインです。
導入とか詳しい使い方については他の方たちが解説してくださっているので、そちらをご参照ください。
使用例
では実際に使ってみます。今回並び替える入れ子のリストは以下になります。
let animals = [
{ emoji: '🐄', name: 'うし' },
{ emoji: '🐕', name: 'いぬ' },
{ emoji: '🐈', name: 'ねこ' },
{ emoji: '🐓', name: 'にわとり', child:[
{ emoji: '🐤', name: 'ひよこ兄' },
{ emoji: '🐤', name: 'ひよこ弟' },
]},
{ emoji:'🐖', name: 'ぶた' }
];
かわいいね
上記リストをHTMLに描画します。
new Vue({
el:'#app',
data: ()=>{
return {
animals: animals
}
}
});
<div id="app">
<ul>
<li v-for="(animal, i) in animals">
<span>{{ i }} : {{ animal.emoji }} {{ animal.name }}</span>
<ul>
<li v-for="(child, j) in animal.child">
<span>{{ i }} - {{ j }} : {{ child.emoji }} {{ child.name }}</span>
</li>
</ul>
</li>
</ul>
</div>
Vue.Draggableで並び替えできるようにします。
<div id="app">
<draggable v-model="animals" :element="'ul'">
<li v-for="(animal, i) in animals">
<span>{{ i }} : {{ animal.emoji }} {{ animal.name }}</span>
<ul>
<draggable v-model="animal.child">
<li v-for="(child, j) in animal.child">
<span>{{ i }} - {{ j }} : {{ child.emoji }} {{ child.name }}</span>
</li>
</draggable>
</ul>
</li>
</draggable>
</div>
最上位のul要素をdraggableに置き換えています。
draggableは何も指定しないとレンダリングの際にdivになってしまうので、:element="'ul'"
でul要素になってくれるよう指定しています。
入れ子になっている部分のリストはli要素をdraggableで囲むようにします。
このdraggableを:element="'ul'"
で指定して<li><span/><ul></ul></li>
ってやろうとするとエラーになります…これよく分からないので知っている方いたら教えてください…
v-modelを使うことも出来るので、HTML側からドラッグアンドドロップで並び替えた結果を、js側のdataで管理しているanimalsリストに反映させています。
indexの値が変わっているのが確認できますね。
また、ちゃんとひよこがにわとりを超えないようになっています。
おわり
例では動物たちを並び替えただけですが、TODOリストに応用してタスクとサブタスクで分けて、優先度に応じて並び替えて、endイベントでlocalStorageに保存…みたいな使い方もできると思います。Vue.jsの入門記事で作ってそのままのTODOリストをちょっと実用的にできるかもしれません。