###### tags: `vue` # Vue.js で Drug&Drop API 使うメモ [Vue Mastery](https://www.vuemastery.com/courses) でDrug&Drop APIについて扱っていたので、忘れないようにメモ ## Drug&Drop API [HTML ドラッグ&ドロップ API](https://developer.mozilla.org/ja/docs/Web/API/HTML_Drag_and_Drop_API)を参照 [draggable](https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/draggable) 属性に対してドラッグイベントを発生させることができる ドロップ関連のイベントなどを含めると * dragstart * dragend * dragover など... ```htmlmixed <p id="p1" draggable="true">この要素はドラッグできます。</p> ``` ## Vueで作用させる 下記の点を記述する、素のjavascriptより簡潔にできる印象 不要なイベントは、デフォルトの処理が発火してしまうので`prevent`で抑制させる * Drag したい要素 * `draggable`属性を付与 * `dragstart`イベントをv-onで設定 (.self は、イベント対象が自身の場合作用させるイベント修飾子) * Drap したい要素 * `drop`イベントをv-onで設定 ```htmlmixed <template> <div> <p id="p1" draggable="true" @dragstart.self="onDrag" @dragover.prevent @dragenter.prevent > この要素はドラッグできます。 </p> <p id="p2" @drop.stop="onDrop" @dragover.prevent @dragenter.prevent > この要素にドロップできます。 </p> </div> </template> <script> export default { mehtods: { onDrag (event) { // Drug イベント処理を記述 }, onDrop (event) { // Drop イベント処理を記述 } } } </script> ``` :::warning (※) Vuetify のようなコンポーネントに作用させる場合、ドキュメントに記載されたイベントトリガーに合わせて設定させる ::: ## Drag&Drop処理関連 [DataTransfer](https://developer.mozilla.org/ja/docs/Web/API/DataTransfer) APIを使用することで、Drag&Drop時の処理を行える * DataTransfer.dropEffect: エフェクト関連 * DataTransfer.effectAllowed: 操作の許可 * DataTransfer.files: ファイル関連 * DataTransfer.getData(): DataTransfer内の指定されたデータを取得 * DataTransfer.setData(): DataTransfer内に指定したデータを設定 ## コンポーネント化 汎用的に使える用にベースコンポーネント化 ### AppDrug.vue --- ```htmlmixed= <template> <div draggable @dragstart.self="onDrag" @dragover.prevent @dragenter.prevent > <slot /> </div> </template> <script> export default { props: { transferData: { type: Object, required: true, default: () => {} } }, methods: { onDrag (e) { e.dataTransfer.effectAllowed = 'move' e.dataTransfer.dropEffect = 'move' e.dataTransfer.setData('payload', JSON.stringify(this.transferData)) } } } </script> ``` ### AppDrop.vue --- ```htmlmixed= <template> <div @drop.stop="onDrop" @dragover.prevent @dragenter.prevent > <slot /> </div> </template> <script> export default { methods: { onDrop (e) { const transferData = JSON.parse(e.dataTransfer.getData('payload')) this.$emit('drop', transferData) } } } </script> ``` ### ベースコンポーネント使用例 --- `transferData`にオブジェクトをpropsし、Drag&Dropを行う ```htmlmixed= <template> <AppDrop @drop="moveTaskOrColumn"> <AppDrag class="task" :transferData="{ type: 'task', fromColumnIndex: columnIndex, fromTaskIndex: taskIndex }" @click.native="goToTask(task)" > <span class="w-full flex-no-shrink font-bold"> {{ task.name }} </span> <p v-if="task.description" class="w-full flex-no-shrink mt-1 xt-sm"> {{ task.description }} </p> </AppDrag> </AppDrop> </template> ``` 以上!