文件拖拽上传功能已经烂大街了,你还不会吗?

本文介绍了如何使用原生JavaScript和Vue实现文件拖拽上传功能,包括阻止浏览器默认行为、处理拖拽事件和封装成Vue组件的过程。
摘要由CSDN通过智能技术生成

说在前面

🖼文件拖拽上传功能现在已经随处可见,大家应该都用过了吧,那么它具体是怎么实现的大家有去了解过吗?今天我们一起来实现一下这个功能,并封装一个拖拽上传组件吧。

效果展示

image.png

AI改图-2023-09-23-23-08-48-720x405.gif

体验地址:jyeontu.xyz/jvuewheel/#…

功能实现

原生JavaScrip实现

首先我们应该先将页面写好:

 

html

复制代码

<!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>

image.png

我们试下直接拖拽图片到页面上是什么效果

AI改图-2023-09-23-21-43-40-720x405.gif

我们发现直接将图片拖拽到页面上会在新页面打开图片,那么我们需要阻止这一个默认行为以允许放置,页面的拖拽行为主要会触发以下几个事件:

dragenter

dragenter 事件在可拖动的元素或者被选择的文本进入一个有效的放置目标时触发。

目标对象是用户直接选择的范围(由用户直接指示作为放置目标的元素),或者 <body> 元素。

dragleave

dragleave 事件在拖动的元素或选中的文本离开一个有效的放置目标时被触发。

此事件不可取消。

dragover

dragover 事件在可拖动的元素或者被选择的文本被拖进一个有效的放置目标时(每几百毫秒)触发。

该事件在放置目标上触发。

drop

drag 事件在用户拖动元素或选择的文本时,每隔几百毫秒就会被触发一次。

效果实现
获取上传框和预览框元素
 

javascript

复制代码

const dropZone = document.getElementById("drop-zone"); const uploadedImage = document.getElementById("uploaded-image");

图片进入上传框时,为上传框加一层灰色蒙层

监听上传框的dragenter事件,在图片移动进入上传框时改变上传框的背景颜色。

 

javascript

复制代码

dropZone.addEventListener("dragenter", function (event) { dropZone.style.backgroundColor = "#f7f7f7"; });

图片离开上传框时,去除上传框的灰色蒙层

监听上传框的dragleave事件,在图片移出上传框时去除上传框的背景颜色。

 

javascript

复制代码

dropZone.addEventListener("dragleave", function (event) { dropZone.style.backgroundColor = ""; });

阻止浏览器默认行为,例如打开文件

dragoverdrop事件都会触发浏览器打开文件,我们需要阻止其默认行为。

 

javascript

复制代码

dropZone.addEventListener("dragover", function (event) { event.preventDefault(); }); dropZone.addEventListener("drop", function (event) { event.preventDefault(); });

获取拖拽上传的文件

拖拽释放会触发drop事件,我们只需要监听drop事件,获取到拖拽的文件列表event.dataTransfer.files即可。

 

javascript

复制代码

dropZone.addEventListener("drop", function (event) { event.preventDefault(); dropZone.style.backgroundColor = ""; const file = event.dataTransfer.files[0]; handleFile(file); });

处理上传文件,为图片时设置预览图

判断上传的文件是否为图片,我们只需要判断上传文件的type是否为image开头,是的话我们可以将其转为dataUrl文件并设置预览。

 

javascript

复制代码

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实现一个拖拽上传功能之后,我们也能很容易得将其封装成一个vue组件。

监听拖拽事件

在vue中,我们直接通过@dragover@dragleave@drop即可监听元素的拖拽事件。

 

html

复制代码

<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其实都是一样的。

 

javascript

复制代码

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); } }

获取到上传文件并传递给父组件

获取到上传的文件后,我们不应该组件内直接处理文件了,将其传递给父组件进行处理即可。

 

javascript

复制代码

uploadFile(file) { this.$emit("uploadFile", file); }

组件完整代码

功能逻辑与原生JavaScrip基本相同,这里也不重复描述了,直接看代码吧:

 

javascript

复制代码

<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>

image.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜栩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值