[[Vue]]でファイルをドラッグ&ドロップする場合のベーシックな実装方法。[[Tailwind CSS]]は利用するケースを想定。 > [!hint] > > ライブラリを使って並び替える方法は [[📰Vueで異なるモデルで構成された2つのリストをドラッグ&ドロップする方法の調査]] を参照。 ## 想定ユースケース 以下のようなケースを想定。 - 特定エリアにドラッグすると色が変わる - ドロップするとFileを受け取る ### VueUseを使わない > [!caution] > 特に理由がなければこのあとの[[#VueUseを使う]]方法を推奨する。 ```html <script setup lang="ts"> import { ref } from "vue"; const isDragOver = ref(false); const handleDrop = (payload: DragEvent) => { console.log(payload.dataTransfer?.files[0]); }; const handleClickButton = (event: MouseEvent) => { console.log(event.target); }; </script> <template> <div class="flex justify-center items-center h-screen"> <div class="size-192 text-4xl border-dashed border-2 border-gray-400 rounded-md p-12 transition duration-300" :class="isDragOver ? ['bg-red-200'] : []" @dragover.prevent @dragenter="isDragOver = true" @dragleave="isDragOver = false" @drop.prevent="handleDrop" > <div class="flex flex-col gap-4" :class="{ 'pointer-events-none': isDragOver }" > <div>ここにドロップする</div> <button class="text-xl bg-blue-600 text-white p-2 rounded-lg hover:bg-blue-400 transition duration-300" @click="handleClickButton" > ファイルを選択 </button> </div> </div> </div> </template> ``` ## VueUseを使う [[VueUse]]を使ってファイル選択ボタンの処理もちゃんと実装する。[[useDropZone]]と[[useFileDialog]]使う。 ```html <script setup lang="ts"> import { ref } from "vue"; import { useDropZone, useFileDialog } from "@vueuse/core"; const dropZoneRef = ref<HTMLDivElement>(); const { isOverDropZone } = useDropZone(dropZoneRef, { onDrop: (files: File[] | null) => { console.log(files?.[0]); }, }); const { open: openFileDialog, onChange } = useFileDialog(); onChange((files) => { console.log(files?.[0]); }); </script> <template> <div class="flex justify-center items-center h-screen"> <div ref="dropZoneRef" class="size-192 text-4xl border-dashed border-2 border-gray-400 rounded-md p-12 transition duration-300" :class="isOverDropZone ? ['bg-red-200'] : []" > <div class="flex flex-col gap-4"> <div>ここにドロップする</div> <button class="text-xl bg-blue-600 text-white p-2 rounded-lg hover:bg-blue-400 transition duration-300" @click=" () => { openFileDialog(); } " > ファイルを選択 </button> </div> </div> </div> </template> ```