目次
Vue.Draggableとは
Vue.Draggableは、Vue.jsをベースとしたドラッグ&ドロップコンポーネントライブラリです。
Vue.jsのアーキテクチャに基づいて設計されており、ドラッグ&ドロップの機能を簡単かつ効果的に実装できます。
コンパイルを必要としないUMD用のJSファイルが提供されており、jQueryからの切り替えも容易に行うことができます。
また、単純なドラッグ&ドロップの機能から、複数のエリアを移動することも可能で、スマートフォンにも対応しています。
タッチイベントによる移動も可能となっており、モバイルフレンドリーなWebアプリケーションを構築することができます。
総じて、Vue.Draggableは、Vue.jsの生産性を高め、開発効率を向上させるための素晴らしいツールであり、特にドラッグ&ドロップの実装において優れた機能性と使いやすさを提供します。
Webアプリケーションの開発において、Vue.Draggableを利用することで、柔軟なUI/UXを実現することができます。
【動画サイズ:87KB】
環境
この記事は、以下の管理人の検証環境にて記事にしています。
vue.js | 3.2.26 |
Vue.Draggable | 4.0.2 |
Vue2対応
Vue2を使用する場合は下記のURL
https://www.kabanoki.net/1712/
ライブラリの取得
ライブラリを取得するには、npm, yarn, CDNのどれか一つを使用します。
npm
npm i -S vuedraggable@next
yarn
yarn add vuedraggable@next
CDN
<script src="https://cdn.jsdelivr.net/npm/[email protected]/Sortable.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuedraggable.umd.min.js"></script>
直接「Vue.Draggable」のリポジトリを取得する場合は、以下のURLから取得できます。
https://github.com/SortableJS/vue.draggable.next
導入手順
管理人が行った、動作確認サンプルを実装するために、以下の手順でソースコードを導入していきます。
このサンプルは、1つのエリアの中で並び順を変更するものになります。
step
1ライブラリの呼び出し
まずライブラリを呼び出す為に、以下の2通りのケースで呼び出します。
ES6等で実装する場合
import draggable from 'vuedraggable'
CDNで実装する場合
const draggable = window['vuedraggable'];
step
2テンプレートを準備
<draggable>
の内部がドラッグ可能なエリアになります。
v-model プロパティにループする配列を設定します。list プロパティでも同様に行うことができますが、処理の仕方が少し違うようです。リストの囲みタグはtagプロパティへ設定します。ulやdivのような外部要素タグを設定して使用します。item-key にループ要素のkeyになる値を設定します。
<draggable>
の内部は、自動でループ処理が行われます。Slotsのelementの中に、配列の個別データが格納されます。
ポイント
ループに使う配列は、data から直接渡しても良いですし、computed を使っても大丈夫です。
<div id="app"> <draggable v-model="items" item-key="no" tag="ul"> <template #item="{ element, index }"> <li>{{element.name}}-(No.{{element.no}})</li> </template> </draggable> </div>
注意ポイント
リストのitem-keyプロパティを忘れずに設定しましょう!
これが無いと要素の追加・削除で、バグが多発するので必ず設定しましょう!
step
3Vueインスタンスを設定
Step1で取得したdraggableを components
プロパティに設定します。
今回のサンプルはdateから直接ループに値を渡します。
リスト用の配列データitemsを設定します。
const App = { data() { return { items: [ {no:1, name:'キャベツ', categoryNo:'1'}, {no:2, name:'ステーキ', categoryNo:'2'}, {no:3, name:'リンゴ', categoryNo:'3'} ] } }, components: { draggable: draggable }, } Vue.createApp(App).mount('#app');
step
4リストにスタイルを適用する
Vue.DraggableにはjQuery uiのような専用のスタイルが無いので、見た目を整えるためにスタイルを自作する必要があります。
今回はサンプル用に下記のようなスタイルを適用します。
ul { list-style-type: none; } li { cursor: pointer; padding: 10px; border: solid #ddd 1px; }
サンプル
今回のソースを実際に触って確認できるようにデモを用意しました。
See the Pen
Vue.Draggable single by カバの樹 (@kabanoki)
on CodePen.0
複数エリアの導入手順
次に上の1つのエリア内で並び順を変更するサンプルを参考にして、二つのエリアをドラッグ移動できるサンプルを実装するための導入を行ってみます。
以下の手順にしたがって、実装を行っていきます。
1.テンプレートを準備
ドラッグ移動が可能なエリアを用意する為に、<draggable>
を2つ準備します。
2つの<draggable>
エリアにgroup プロパティでITEMSを持たせます。
これで2つ<draggable>
エリアを自由に行き来させることができます。
<div id="app" class="container"> <div id="box1" class="box"> <draggable v-model="items" item-key="no" tag="ul" group="ITEMS"> <template #item="{ element, index }"> <li>{{element.name}}-(No.{{element.no}})</li> </template> </draggable> </div> <div id="box2" class="box"> <draggable v-model="items2" item-key="no" tag="ul" group="ITEMS"> <template #item="{ element, index }"> <li>{{element.name}}-(No.{{element.no}})</li> </template> </draggable> </div> </div>
注意ポイント
エリア内のリストが空になると再ドラッグがし辛くなります。
<draggable>
に、スタイルでpadding:3px
みたいに厚みを持たせてあげるとドラッグがし易くなります。
2. 複数のdraggableリスト用に配列を用意する
2つのドラッグエリア用のリストをdataに用意します。
const App = { data() { return { items:[ {no:1, name:'キャベツ', categoryNo:'1'}, {no:2, name:'ステーキ', categoryNo:'2'} ], items2:[ {no:5, name:'きゅうり', categoryNo:'1'}, {no:6, name:'ハンバーグ', categoryNo:'2'} ] } }, components: { draggable: draggable }, } Vue.createApp(App).mount('#app');
サンプル
今回のソースを実際に触って確認できるようにデモを用意しました。
See the Pen
Vue.Draggable multiple by カバの樹 (@kabanoki)
on CodePen.0
イベント
ドラッグイベントは、任意のタイミングで動作します。
9種類のタイミングが用意されています。
イベント一覧
イベント | タイミング |
start | ドラッグ開始したとき |
add | 要素が追加されたとき |
remove | 要素を削除されたとき |
update | ドラッグで要素の移動が完了したとき |
end | ドラッグが完了したときの最後に動作します |
choose | ドラッグ要素を選択したとき |
unchoose | ドラッグ要素を選択から外したとき |
sort | 並び順を変更したときのupdateの後、endの前に動作する |
filter | フィルターされたとき |
clone | ドラッグ時のシャドークローンが生成されたとき |
イベント導入例
今回はendイベントを例に使って解説します。
step
1onEnd関数を作成する
まずイベントを作成します。
onEndというイベントをmethodsに作成します。
onEndの第一引数を設定しておくと、ドラッグアイテムのイベント情報が格納されます。
これで、ドラッグ後にイベントを反応させられます。
methods: { onEnd: function(originalEvent){ console.log(originalEvent);//originalEventは イベントを取得できる } }
step
2@end="onEnd"をコンポーネントに設定する
上記で作成したonEndイベントを<draggable>
に設定します。
<draggable v-model="myArray" @end="onEnd">
リストに新規で追加する方法
あらかじめ用意されたリストに新規でドラッグ要素を追加したい場合は、以下が参考になります。
スクリプト
リストの配列にarray.push
を使って、新規のアイテムを追加します。
今回はdoAddというmedhodsを作成して、items配列にpush()
でオブジェクトを追加していきます。
const App = { data() { return { items: [ {no:1, name:'キャベツ', categoryNo:'1'}, {no:2, name:'ステーキ', categoryNo:'2'}, {no:3, name:'リンゴ', categoryNo:'3'} ], newNo: 4 } }, components: { draggable: draggable }, methods: { doAdd:function(){ let self = this; let no = 0; // itemsの中の一番大きなnoを取得して1を足す if(self.items.concat().length > 0){ no = Math.max.apply(null,self.items.concat().map(function(item){return item.no;})) +1; self.newNo = self.newNo < no ? no:self.newNo; } // itemsにアイテムを追加 this.items.push({ no: this.newNo, name:'追加リスト'+ this.newNo, categoryNo:'5' }); }, } } Vue.createApp(App).mount('#app');
HTML
ボタンを用意して、クリックするとdoAddイベントが起動します。
<div id="app" class="container"> <button v-on:click="doAdd">追加</button> <div class="p-3"> <draggable v-model="items" item-key="no" tag="ul"> <template #item="{ element, index }"> <li>{{element.name}}-(No.{{element.no}})</li> </template> </draggable> </div> </div>
サンプル
See the Pen
Vue.Draggable add by カバの樹 (@kabanoki)
on CodePen.0
リストから削除する方法
リストの中からドラッグ要素を削除したい場合は、以下が参考になります。
スクリプト
リストの配列からarray.splice
を使って、アイテムを削除します。
doDeleteというmedhodsを作って、引数で配列のindexを受け取って、splice(index, 1)
で削除します。
const App = { data() { return { items: [ {no:1, name:'キャベツ', categoryNo:'1'}, {no:2, name:'ステーキ', categoryNo:'2'}, {no:3, name:'リンゴ', categoryNo:'3'} ], newNo: 4 } }, components: { draggable: draggable }, methods: { doDelete: function(index){ this.items.splice(index, 1); }, } } Vue.createApp(App).mount('#app');
HTML
削除ボタンをクリックしてdoDeleteイベントを起動します。
引数にindexを持たせます。
<div id="app" class="container"> <div class="p-3"> <draggable v-model="items" item-key="no" tag="ul"> <template #item="{ element, index }"> <li>{{element.name}}-(No.{{element.no}}) <span class="del" v-on:click="doDelete(index)">[削除]</span></li> </template> </draggable> </div> </div>
サンプル
See the Pen
Vue.Draggable delete by カバの樹 (@kabanoki)
on CodePen.0
Slots
プロパティ
Slotのプロパティはデフォルトですと、下記の2つになります。
element
リストの要素index
リストのインデックス
<template #item="{ element:item, index:i }">
様に書くことで、別の変数名として取得することが可能です。
footer slot
<draggable v-model="myArray" item-key="id"> <template #item="{element}"> <div> {{element.name}} </div> </template> <template #footer> <button @click="addPeople">Add</button> </template> </draggable>
header slot
<draggable v-model="myArray" item-key="id"> <template #item="{element}"> <div> {{element.name}} </div> </template> <template #header> <button @click="addPeople">Add</button> </template> </draggable>
transition-group の設定方法
<draggable v-model="myArray" tag="transition-group" item-key="id"> <template #item="{element}"> <div> {{element.name}} </div> </template> </draggable>
囲みタグを変更する場合は component-data プロパティに <transition-group>
へ送るプロパティを設定します。
<draggable :component-data="{name: 'list',tag: 'ul'}" v-model="myArray" tag="transition-group" item-key="id"> <template #item="{ element, index }"> <li>{{element}}</li> </template> </draggable>
ドラッグ時の掴める箇所やアニメーションを設定
Vue.Draggableは、Sortable.jsを元にしているので、同ライブラリのオプションを利用することができます。
例えば以下のようなオプションをしようすることができます。
カスタマイズできるモノ
- ドラッグアイテムの掴める箇所を指定する(ハンドラーを設定)
- ドラッグアイテムの移動時にアニメーションを設定する
- ドラッグ可能にするまでに時間を設定する
Sortable.jsのオプションを実装してみたい方は、以下の記事が参考になります。
-
参考Vue.DraggableでSortable.jsのオプションを使う
この記事は、「Vue.Draggable」でSortable.jsのオプションを使う方法を書いています。
続きを見る
リストの並び順をブラウザに保存する
WEBアプリなどでブラウザに並び順を保存したい時などは、下記の記事が参考になります。
-
参考「Vue.Draggable」の並び順をブラウザに保存する方法
以前から「Vue.Draggable」の並び順をブラウザに保存したいなあと思っていました。先日「vue-ls」というブラザストレージを操作するライブラリの記事を書いた際に、勢いで「Vue.Draggable」と組み合わせたシステムを作成しました。
続きを見る
ドラッグリストをフィルタリングする
特定の文字を含むリストを並べ替えたり、カテゴリーで絞り込みをしたい時の参考記事を書きました!↓
-
参考Vue.Draggableでフィルタリングされたリストを使用する
Vue.Draggableを使いながらリストをフィルタする機能が欲しいと思いました。
しかし、Vue.Draggableの特性と言いますか、制限のようなものでcomputedが使用できません。
そこで別のやり方で実装しました。続きを見る
テーブルの列を並び替える
テーブルの列の順番を並び替える方法を記事にしました。
下記の記事を参考にしてください。
後日記事にします。
さいごに
Vue.js製のドラッグ&ドロップコンポートネントライブラリでした。
管理人が実務で触った感触的には、ドラッグ&ドロップするならこのライブラリを選んでおけば問題ないと思います。
よっぽど特殊なことをやりたいなら、このライブラリをカスタマイズするよりも別のライブラリを使うのが無難だと思います。
そういう意味では、Vue.js製のドラッグ&ドロップ系ライブラリは結構種類が豊富です。
今後そういったライブラリをご紹介していければと思います。
おまけ
別のライブラリになってしまいますが、ツリー形式にドラッグ要素を配置できるものもあります。
これを使えばWordpressのメニュー的なのも作れそうですね。
-
参考「vue-draggable-nested-tree」でドラッグ要素をツリー形式で配置する
vue-draggable-nested-treeは、ドラッグ要素をツリー形式に配置することが可能なdraggable&droppableコンポーネントです。tree-helper.js を使用することで、折りたたみを実装することも可能です。簡単に実装できるコピペと触って体感できるサンプルを掲載しています。
続きを見る
今日はこの辺でー