久しぶりにVue.jsの記事を書きます。
TrelloやGithubのカンバンのようなタスク管理を作りたいと考え、良い感じのライブラリないかな、と探していたところ、vue-draggableを見つけました。
https://github.com/SortableJS/Vue.Draggable
Sortable.jsがベースのようで、かなり簡単にドラッグ機能が実装できます。
今回はこちらのライブラリを紹介したいと思います。
今回もJSFiddleを使用します。
しばらく使ってませんでしたが、リニューアルしてましたね。
JSフレームワークをVueで選択しておけば、あとはそのままで良さそうです。
見た目を良くするために、Materializeを使用しています。
CDNのURLをResourcesに登録します。
また、今回の主役でもあるvue-draggableも登録します。
CDNを使いますが、 npm
や yarn
を使用する場合は、下記でインストールできます。
$ npm install vuedraggable # or $ yarn add vuedraggable
tasks
というプロパティに配列でタスクを定義して、それを v-for
でループさせています。ただ、そのリスト要素を <draggable>
というカスタムタグで囲んでいます。
これが、ドラッグ可能な領域を定義しています。
<draggable :list="tasks" class="dragArea"> <!-- **** --> </draggable>
:list
はこの領域の配列プロパティを指定します。
今回は tasks
になります。class
はHTMLのclass要素です。
これだけで、ドラッグ機能による並べ替えが実装できます。
移動する前に、その要素が移動可能かチェックしたい、
または移動した後にローカルストレージやサーバーに保存する、といったことをしたくなると思います。
このためのイベントも用意されています。
先ほどのサンプルを少し修正しました。
move
は動かすタイミングで発火するイベントです。
例では、「Meeting」だったら動かさないようにしました。
コールバックメソッドでBooleanを返すことで、動かして良いのか悪いのか許可させることができます。
試していただくと分かると思いますが、「Meeting」を動かしても元の位置に固定されていると思います。
後述する end
とは違い、カスタムタグ内では :move
で指定することも注意が必要です。
コールバックメソッドの引数で取得できるプロパティは下記をご参照ください。
https://github.com/SortableJS/Vue.Draggable#move
動き終わった後の end
もあります。
他にも動き出しの start
も用意されています。
今回の例では、動き終わったら alert
を出すようにしました。move
とは違って、コールバックメソッドの引数のプロパティが違うので、注意が必要です。
また、カスタムタグ内では @end
で定義します。
少しTrelloに近づけるため、2列間でタスクの受け渡しをしたいと思います。
左列から右列、右列から左列に移動できるかと思います。
また、ちゃんとイベントも発火します。
方法としては、まず2つのプロパティを用意し( `unfinishedTasks` 、 `finishedTasks` )、それぞれの行でこれらを表示させます。
また、カスタムタグである `draggable` は下記のようにしてあります。
<draggable :list="unfinishedTasks" class="dragArea0" :move="beforeMove" @end="onEnd" :options="{group:'tasks'}"> <!-- *** --> </draggable>
`:options` で色々オプションを設定できるのですが、今回は `group` を使いました。
これは、それぞれの配列がどのグループに属するか定義し、配列間の受け渡しをするようにします。
これを設定しておかないと、左列から右列、右列から左列への移動ができなくなります。
片方を空配列にすると、(そのままでは)移動できないようです。
Sortable.js のコードを読んだ訳ではないですが、恐らく割り込み要素から挿入位置を計算しているため、割り込み先がいないと計算できないのではないかと推測しています。
私は、ダミーで1つ動かない要素をつけて対応しましたが、もっと良い方法がありそうです。
(もしくはモジュール内にオプションで存在している。)
今回はモジュールの紹介でした。
触っていると、もう少しVue.jsの基本を理解しなければ、と思うので、次回あたりはまたドキュメントをやりたいなと考えています。
このモジュールをインポートして、コンポーネント内で使用する場合は、カスタムタグの宣言が必要そうです。
もし、「こんなタグ知らないよ」みたいなエラーが出たら、下記のコードを追加してみてください。
var app = new Vue({ // ... components: { draggable }, // ... });