27
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Vue.js】入れ子のリストをドラッグアンドドロップで各階層の中だけで並び替えする

Last updated at Posted at 2018-06-28

こんにちは。Vue.js勉強中の者です。

ドラッグアンドドロップでリストを並び替えて色々したいって時あるじゃないですか。
しかも入れ子のリストで、子が親を飛び越えたりせずに同じ階層同士でしか並び替えしたくないって時もあるじゃないですか。あるか?
jQueryUIでも頑張れば出来そうですが、Vue.js導入してVue.Draggableを使えばアホ簡単に出来たのでその備忘録です。

Vue.Draggable

ドラッグアンドドロップで並び替えすることをうまいことやってくれるプラグインです。
導入とか詳しい使い方については他の方たちが解説してくださっているので、そちらをご参照ください。

使用例

では実際に使ってみます。今回並び替える入れ子のリストは以下になります。

test.js
let animals = [
    { emoji: '🐄', name: 'うし' },
    { emoji: '🐕', name: 'いぬ' },
    { emoji: '🐈', name: 'ねこ' },
    { emoji: '🐓', name: 'にわとり', child:[
        { emoji: '🐤', name: 'ひよこ兄' },
        { emoji: '🐤', name: 'ひよこ弟' },
    ]},
    { emoji:'🐖', name: 'ぶた' }
];

かわいいね

上記リストをHTMLに描画します。

test.js
new Vue({
    el:'#app',
    data: ()=>{
        return {
            animals: animals
        }
    }
});
index.html
<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>

こうなります
animals.png

Vue.Draggableで並び替えできるようにします。

index.html
<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リストに反映させています。
animals_sort.gif

indexの値が変わっているのが確認できますね。
また、ちゃんとひよこがにわとりを超えないようになっています。

おわり

例では動物たちを並び替えただけですが、TODOリストに応用してタスクとサブタスクで分けて、優先度に応じて並び替えて、endイベントでlocalStorageに保存…みたいな使い方もできると思います。Vue.jsの入門記事で作ってそのままのTODOリストをちょっと実用的にできるかもしれません。

27
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?