基于Vue實現(xiàn)文件拖拽上傳功能
效果展示


體驗地址:jyeontu.xyz/jvuewheel/#/JDragUploadView
功能實現(xiàn)
原生JavaScrip實現(xiàn)
首先我們應(yīng)該先將頁面寫好:
<!DOCTYPE html>
<html lang="en">
<head>
<title>點擊或拖拽上傳并顯示圖片</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>點擊或拖拽上傳并顯示圖片示例</h1>
<div id="drop-zone">點擊或拖拽上傳圖片</div>
<img id="uploaded-image" src="" alt="上傳的圖片" />
<script>
</script>
</body>
</html>

我們試下直接拖拽圖片到頁面上是什么效果

我們發(fā)現(xiàn)直接將圖片拖拽到頁面上會在新頁面打開圖片,那么我們需要阻止這一個默認行為以允許放置,頁面的拖拽行為主要會觸發(fā)以下幾個事件:
dragenter
dragenter 事件在可拖動的元素或者被選擇的文本進入一個有效的放置目標時觸發(fā)。
目標對象是用戶直接選擇的范圍(由用戶直接指示作為放置目標的元素),或者 <body> 元素。
dragleave
dragleave 事件在拖動的元素或選中的文本離開一個有效的放置目標時被觸發(fā)。
此事件不可取消。
dragover
dragover 事件在可拖動的元素或者被選擇的文本被拖進一個有效的放置目標時(每幾百毫秒)觸發(fā)。
該事件在放置目標上觸發(fā)。
drop
drag 事件在用戶拖動元素或選擇的文本時,每隔幾百毫秒就會被觸發(fā)一次。
效果實現(xiàn)
獲取上傳框和預(yù)覽框元素
const dropZone = document.getElementById("drop-zone");
const uploadedImage = document.getElementById("uploaded-image");
圖片進入上傳框時,為上傳框加一層灰色蒙層
監(jiān)聽上傳框的dragenter事件,在圖片移動進入上傳框時改變上傳框的背景顏色。
dropZone.addEventListener("dragenter", function (event) {
dropZone.style.backgroundColor = "#f7f7f7";
});
圖片離開上傳框時,去除上傳框的灰色蒙層
監(jiān)聽上傳框的dragleave事件,在圖片移出上傳框時去除上傳框的背景顏色。
dropZone.addEventListener("dragleave", function (event) {
dropZone.style.backgroundColor = "";
});
阻止瀏覽器默認行為,例如打開文件
dragover和drop事件都會觸發(fā)瀏覽器打開文件,我們需要阻止其默認行為。
dropZone.addEventListener("dragover", function (event) {
event.preventDefault();
});
dropZone.addEventListener("drop", function (event) {
event.preventDefault();
});
獲取拖拽上傳的文件
拖拽釋放會觸發(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è)置預(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實現(xiàn)一個拖拽上傳功能之后,我們也能很容易得將其封裝成一個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其實都是一樣的。
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)直接處理文件了,將其傳遞給父組件進行處理即可。
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: "將文件拖放到此處或點擊上傳",
},
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實現(xiàn)文件拖拽上傳功能的詳細內(nèi)容,更多關(guān)于Vue文件拖拽上傳的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue+element-ui前端使用print-js實現(xiàn)打印功能(可自定義樣式)
Print.js主要是為了幫助我們直接在瀏覽器中開發(fā)打印功能,下面這篇文章主要給大家介紹了關(guān)于vue+element-ui前端使用print-js實現(xiàn)打印功能(可自定義樣式)的相關(guān)資料,需要的朋友可以參考下2022-11-11
Vue利用openlayers實現(xiàn)點擊彈窗的方法詳解
點擊彈窗其實就是添加一個彈窗圖層,然后在點擊的時候讓他顯示出來罷了。本文將利用openlayers實現(xiàn)這一效果,快跟隨小編一起學(xué)習(xí)一下吧2022-06-06
vite打包出現(xiàn)"default"?is?not?exported?by?"no
這篇文章主要給大家介紹了關(guān)于vite打包出現(xiàn)"default"?is?not?exported?by?"node_modules/...問題解決的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2023-11-11

