基于Vue實(shí)現(xiàn)文件拖拽上傳功能
效果展示
體驗(yàn)地址:jyeontu.xyz/jvuewheel/#/JDragUploadView
功能實(shí)現(xiàn)
原生JavaScrip實(shí)現(xiàn)
首先我們應(yīng)該先將頁面寫好:
<!DOCTYPE html> <html lang="en"> <head> <title>點(diǎn)擊或拖拽上傳并顯示圖片</title> <style> body { display: flex; flex-direction: column; } h1 { text-align: center; } #drop-zone { width: 300px; height: 200px; border: 2px dashed #ccc; margin: 20px auto; text-align: center; line-height: 200px; font-size: 18px; } #uploaded-image { max-width: 300px; max-height: 300px; margin: 20px auto; } </style> </head> <body> <h1>點(diǎn)擊或拖拽上傳并顯示圖片示例</h1> <div id="drop-zone">點(diǎn)擊或拖拽上傳圖片</div> <img id="uploaded-image" src="" alt="上傳的圖片" /> <script> </script> </body> </html>
我們?cè)囅轮苯油献D片到頁面上是什么效果
我們發(fā)現(xiàn)直接將圖片拖拽到頁面上會(huì)在新頁面打開圖片,那么我們需要阻止這一個(gè)默認(rèn)行為以允許放置,頁面的拖拽行為主要會(huì)觸發(fā)以下幾個(gè)事件:
dragenter
dragenter
事件在可拖動(dòng)的元素或者被選擇的文本進(jìn)入一個(gè)有效的放置目標(biāo)時(shí)觸發(fā)。
目標(biāo)對(duì)象是用戶直接選擇的范圍(由用戶直接指示作為放置目標(biāo)的元素),或者 <body>
元素。
dragleave
dragleave
事件在拖動(dòng)的元素或選中的文本離開一個(gè)有效的放置目標(biāo)時(shí)被觸發(fā)。
此事件不可取消。
dragover
dragover
事件在可拖動(dòng)的元素或者被選擇的文本被拖進(jìn)一個(gè)有效的放置目標(biāo)時(shí)(每幾百毫秒)觸發(fā)。
該事件在放置目標(biāo)上觸發(fā)。
drop
drag
事件在用戶拖動(dòng)元素或選擇的文本時(shí),每隔幾百毫秒就會(huì)被觸發(fā)一次。
效果實(shí)現(xiàn)
獲取上傳框和預(yù)覽框元素
const dropZone = document.getElementById("drop-zone"); const uploadedImage = document.getElementById("uploaded-image");
圖片進(jìn)入上傳框時(shí),為上傳框加一層灰色蒙層
監(jiān)聽上傳框的dragenter
事件,在圖片移動(dòng)進(jìn)入上傳框時(shí)改變上傳框的背景顏色。
dropZone.addEventListener("dragenter", function (event) { dropZone.style.backgroundColor = "#f7f7f7"; });
圖片離開上傳框時(shí),去除上傳框的灰色蒙層
監(jiān)聽上傳框的dragleave
事件,在圖片移出上傳框時(shí)去除上傳框的背景顏色。
dropZone.addEventListener("dragleave", function (event) { dropZone.style.backgroundColor = ""; });
阻止瀏覽器默認(rèn)行為,例如打開文件
dragover
和drop
事件都會(huì)觸發(fā)瀏覽器打開文件,我們需要阻止其默認(rèn)行為。
dropZone.addEventListener("dragover", function (event) { event.preventDefault(); }); dropZone.addEventListener("drop", function (event) { event.preventDefault(); });
獲取拖拽上傳的文件
拖拽釋放會(huì)觸發(fā)drop
事件,我們只需要監(jiān)聽drop
事件,獲取到拖拽的文件列表event.dataTransfer.files
即可。
dropZone.addEventListener("drop", function (event) { event.preventDefault(); dropZone.style.backgroundColor = ""; const file = event.dataTransfer.files[0]; handleFile(file); });
處理上傳文件,為圖片時(shí)設(shè)置預(yù)覽圖
判斷上傳的文件是否為圖片,我們只需要判斷上傳文件的type是否為image
開頭,是的話我們可以將其轉(zhuǎn)為dataUrl文件并設(shè)置預(yù)覽。
function handleFile(file) { if (file && file.type.startsWith("image/")) { const reader = new FileReader(); reader.onload = function (event) { uploadedImage.src = event.target.result; }; reader.readAsDataURL(file); } }
封裝為vue組件
知道了原生js實(shí)現(xiàn)一個(gè)拖拽上傳功能之后,我們也能很容易得將其封裝成一個(gè)vue組件。
監(jiān)聽拖拽事件
在vue中,我們直接通過@dragover
、@dragleave
、@drop
即可監(jiān)聽元素的拖拽事件。
<div class="upload-area" @dragover.prevent="handleDragOver" @dragleave="handleDragLeave" @drop.prevent="handleDrop" @click="handleUploadClick" > <p v-if="!isDragging" class="tip-text">{{ tipText }}</p> <p v-else>{{ tipConfirmText }}</p> </div>
事件的處理邏輯和原生js其實(shí)都是一樣的。
methods: { handleDragOver(event) { event.preventDefault(); this.isDragging = true; }, handleDragLeave() { this.isDragging = false; }, handleDrop(event) { event.preventDefault(); this.isDragging = false; const file = event.dataTransfer.files[0]; this.uploadFile(file); } }
獲取到上傳文件并傳遞給父組件
獲取到上傳的文件后,我們不應(yīng)該組件內(nèi)直接處理文件了,將其傳遞給父組件進(jìn)行處理即可。
uploadFile(file) { this.$emit("uploadFile", file); }
組件完整代碼
功能邏輯與原生JavaScrip基本相同,這里也不重復(fù)描述了,直接看代碼吧:
<template> <div class="drag-upload"> <div class="upload-area" @dragover.prevent="handleDragOver" @dragleave="handleDragLeave" @drop.prevent="handleDrop" @click="handleUploadClick" > <p v-if="!isDragging" class="tip-text">{{ tipText }}</p> <p v-else>{{ tipConfirmText }}</p> </div> <input type="file" ref="fileInput" style="display: none" @change="handleFileSelected" /> </div> </template> <script> export default { name: "JDragUpload", props: { tipText: { type: String, default: "將文件拖放到此處或點(diǎn)擊上傳", }, tipConfirmText: { type: String, default: "釋放文件以上傳", }, }, data() { return { isDragging: false, }; }, methods: { handleDragOver(event) { event.preventDefault(); this.isDragging = true; }, handleDragLeave() { this.isDragging = false; }, handleDrop(event) { event.preventDefault(); this.isDragging = false; const file = event.dataTransfer.files[0]; this.uploadFile(file); }, handleUploadClick() { this.$refs.fileInput.click(); }, handleFileSelected() { const file = this.$refs.fileInput.files[0]; this.uploadFile(file); }, uploadFile(file) { this.$emit("uploadFile", file); }, }, }; </script> <style lang="less" scoped> .drag-upload { display: flex; align-items: center; justify-content: center; height: 100%; width: 100%; border: 2px dashed #ccc; .upload-area { display: flex; align-items: center; justify-content: center; height: 100%; width: 100%; background-color: #f0f0f0; cursor: pointer; .tip-text { text-align: center; } } } </style>
以上就是基于Vue實(shí)現(xiàn)文件拖拽上傳功能的詳細(xì)內(nèi)容,更多關(guān)于Vue文件拖拽上傳的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue+element-ui前端使用print-js實(shí)現(xiàn)打印功能(可自定義樣式)
Print.js主要是為了幫助我們直接在瀏覽器中開發(fā)打印功能,下面這篇文章主要給大家介紹了關(guān)于vue+element-ui前端使用print-js實(shí)現(xiàn)打印功能(可自定義樣式)的相關(guān)資料,需要的朋友可以參考下2022-11-11Vue利用openlayers實(shí)現(xiàn)點(diǎn)擊彈窗的方法詳解
點(diǎn)擊彈窗其實(shí)就是添加一個(gè)彈窗圖層,然后在點(diǎn)擊的時(shí)候讓他顯示出來罷了。本文將利用openlayers實(shí)現(xiàn)這一效果,快跟隨小編一起學(xué)習(xí)一下吧2022-06-06VUE項(xiàng)目中加載已保存的筆記實(shí)例方法
在本篇文章里小編給大家整理了一篇關(guān)于VUE項(xiàng)目中加載已保存的筆記實(shí)例方法,有興趣的讀者們可以參考下。2019-09-09vite打包出現(xiàn)"default"?is?not?exported?by?"no
這篇文章主要給大家介紹了關(guān)于vite打包出現(xiàn)"default"?is?not?exported?by?"node_modules/...問題解決的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11