Edited at

Vue.jsのリストレンダリングとhtml5のドラッグ&ドロップの実装

More than 1 year has passed since last update.


注意事項

この記事は vue.js v1.x でのみ動作確認済みです。 

v2.x では orderBy など動作しない記述がございますので、ご注意ください。

公式サイトではmousedownやtouchstartなどのイベントをトリガーに実装したサンプルがあります。これをうまく使えばドラッグ&ドロップの実装もできそうですが、今回はhtml5のdraggableを使用してみました。


公式サイトより

@mousedown="startDrag"

@touchstart="startDrag"
@mousemove="onDrag"
@touchmove="onDrag"
@mouseup="stopDrag"
@touchend="stopDrag"
@mouseleave="stopDrag"


デモと実際のコードはこちら

DnD Vue.js(codepen)


解説

HTML5からdraggable="true"とすることで、ドラッグ可能な要素にすることができます。

こちらの記事を参考に勉強しました。

ネイティブ HTML5 ドラッグ&ドロップ


html

<ul class="dropArea">

<li class="draggable" v-for="item in items | orderBy 'index'"
draggable="true"
@dragstart="dragstart(item, $event)"
@dragend="dragend"
@dragenter="dragenter(item)"
>{{item.text}}</li>
</ul>

cssはお好みで適当に。


css

.dropArea {

padding: 0;
margin: 0;
}
.dropArea .draggable {
list-style: none;
margin: 10px;
padding: 0;
width: 100px;
height: 40px;
background-color: #3498db;
}

ドラッグした要素を記憶しておき、dragenterをトリガーに、itemsindexを入れ替えます。indexkeyとして、表示はhtmlのほうでv-for="item in items | orderBy 'index'"という形で自動ソートさせています。


javascript

var app = new Vue({

el: 'body',
data: {
draggingItem: undefined,
items: [{
text: "A",
index: 0
},{
text: "B",
index: 1
},{
text: "C",
index: 3
},{
text: "D",
index: 2
}]
},

methods: {
dragstart (item,e) {
this.draggingItem = item
e.target.style.opacity = 0.5;
},
dragend (e) {
e.target.style.opacity = 1;
},
dragenter (item) {
const tempIndex = item.index;
item.index = this.draggingItem.index
this.draggingItem.index = tempIndex
}
}
})


入れ替え動作に対して、アニメーションを実装しようと思ったのですが、position: absolutefixedを使用した形でしか思いつかなかったので、やめました。


Vue.jsでバインディング可能なイベント一覧です。


バインディング可能なユーザーからのイベント(一部)

@click

@submit
@keyup
@mousedown
@mousemove
@mouseup
@mouseleave
@touchstart
@touchmove
@touchend
@dragstart
@dragenter
@dragleave
@dragover
@dragend

これって、公式サイト(events)に整理された情報がないのですが、DOMのイベント(MDN参照)が色々と使えるという認識であっていますでしょうか?お詳しい方いらっしゃれば是非コメントお願いします!


以上です。

配列のデータは簡単に追加や削除の機能を実装することもできるので、用途に応じて拡張が可能かと思います。他にも「Vue.jsとドラッグ&ドロップ」をテーマにした似た形のコードがありましたが、Vue.jsのバージョンが古かったり、やっぱり自分で書いてみたかったりしたので。


今回のタイトルとは関係ありませんが、Vue.jsの勉強情報

Vue.jsもReactのようにソースが溢れていれば良いのになと日々感じておりますが、個人的にはVueStrapのコードの書き方が最近では、一番勉強になりました。これをBootstrapのように使えるかというと、正直物足りなさすぎますが、コードが気軽に読めるのでありがたかったです。