文件拖拽上传功能已经烂大街了,你还不会吗?
说在前面
🖼文件拖拽上传功能现在已经随处可见,大家应该都用过了吧,那么它具体是怎么实现的大家有去了解过吗?今天我们一起来实现一下这个功能,并封装一个拖拽上传组件吧。
效果展示
体验地址:http://jyeontu.xyz/jvuewheel/#/JDragUploadView
功能实现
原生JavaScrip实现
首先我们应该先将页面写好:
<!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>
我们试下直接拖拽图片到页面上是什么效果
我们发现直接将图片拖拽到页面上会在新页面打开图片,那么我们需要阻止这一个默认行为以允许放置,页面的拖拽行为主要会触发以下几个事件:
dragenter
dragenter
事件在可拖动的元素或者被选择的文本进入一个有效的放置目标时触发。
目标对象是用户直接选择的范围(由用户直接指示作为放置目标的元素),或者 <body>
元素。
dragleave
dragleave
事件在拖动的元素或选中的文本离开一个有效的放置目标时被触发。
此事件不可取消。
dragover
dragover
事件在可拖动的元素或者被选择的文本被拖进一个有效的放置目标时(每几百毫秒)触发。
该事件在放置目标上触发。
drop
drag
事件在用户拖动元素或选择的文本时,每隔几百毫秒就会被触发一次。
效果实现
获取上传框和预览框元素
const dropZone = document.getElementById("drop-zone");
const uploadedImage = document.getElementById("uploaded-image");
图片进入上传框时,为上传框加一层灰色蒙层
监听上传框的dragenter
事件,在图片移动进入上传框时改变上传框的背景颜色。
dropZone.addEventListener("dragenter", function (event) {dropZone.style.backgroundColor = "#f7f7f7";
});
图片离开上传框时,去除上传框的灰色蒙层
监听上传框的dragleave
事件,在图片移出上传框时去除上传框的背景颜色。
dropZone.addEventListener("dragleave", function (event) {dropZone.style.backgroundColor = "";
});
阻止浏览器默认行为,例如打开文件
dragover
和drop
事件都会触发浏览器打开文件,我们需要阻止其默认行为。
dropZone.addEventListener("dragover", function (event) {event.preventDefault();
});
dropZone.addEventListener("drop", function (event) {event.preventDefault();
});
获取拖拽上传的文件
拖拽释放会触发drop
事件,我们只需要监听drop
事件,获取到拖拽的文件列表event.dataTransfer.files
即可。
dropZone.addEventListener("drop", function (event) {event.preventDefault();dropZone.style.backgroundColor = "";const file = event.dataTransfer.files[0];handleFile(file);
});
处理上传文件,为图片时设置预览图
判断上传的文件是否为图片,我们只需要判断上传文件的type是否为image
开头,是的话我们可以将其转为dataUrl文件并设置预览。
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
即可监听元素的拖拽事件。
<divclass="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);}
}
获取到上传文件并传递给父组件
获取到上传的文件后,我们不应该组件内直接处理文件了,将其传递给父组件进行处理即可。
uploadFile(file) {this.$emit("uploadFile", file);
}
组件完整代码
功能逻辑与原生JavaScrip基本相同,这里也不重复描述了,直接看代码吧:
<template><div class="drag-upload"><divclass="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><inputtype="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>
源码
组件体验及文档地址:http://jyeontu.xyz/jvuewheel/#/JDragUploadView
Gitee源码:https://gitee.com/zheng_yongtao/jyeontu-component-warehouse/tree/master/JYeontuComponentWarehouse/packages/JDragUpload
说在后面
🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。
相关文章:

文件拖拽上传功能已经烂大街了,你还不会吗?
说在前面 🖼文件拖拽上传功能现在已经随处可见,大家应该都用过了吧,那么它具体是怎么实现的大家有去了解过吗?今天我们一起来实现一下这个功能,并封装一个拖拽上传组件吧。 效果展示 体验地址:http://jyeon…...

TCP与UDP协议详解!!!
TCP/IP运输层中的两个重要协议 TCP的报文结构 TCP的流量控制 流量控制:让发送方发送速率不要太快,TCP协议使用滑动窗口实现流量控制。 利用滑动窗口机制可以很方便地在TCP连接上实现对发送方的流量控制。 TCP接收方利用自己的接收窗口的大小来限制发送…...

《C++ primer》练习6.36-6.38:书写返回数组引用的函数声明
最近看C primer,看到《C primer》6.3.3练习,要求书写返回数组引用的函数声明,觉得有必要实践记录一下。 这里先总结返回数组的引用的的函数声明写法(下面的Type是数组元素的类型,可以是int、float等,如果要…...
Spring Cloud Gateway快速入门(三)——过滤器
文章目录 前言Gateway内置网关过滤器什么是网关过滤器Gateway内置网关过滤器GlobalFilterPreFilterPostFilter 使用示例 Gateway全局网关过滤器什么是全局网关过滤器使用全局网关过滤器注册全局网关过滤器使用全局网关过滤器 全局网关过滤器和Gateway内置网关过滤器的区别1. 注…...
vue3相比vue2的优点
一、响应式: (1)vue2:内置的Object.defineProperty将data中的数据转化成响应式数据的,它会将data中的每个属性都转换为具有getter和setter的响应式属性 Object.defineProperty是一个内置的方法,它用于定义…...

gitee-快速设置
快速设置— 如果你知道该怎么操作,直接使用下面的地址 HTTPS SSH: gitgitee.com:liuzl33078235/esp-idf.git 我们强烈建议所有的git仓库都有一个README, LICENSE, .gitignore文件 初始化 readme 文件 Git入门?查看 帮助 , Visual Studio / TortoiseG…...

将切分的图片筛选出有缺陷的
将切分的图片筛选出有缺陷的 需求代码 需求 由于之前切分的图像有一些存在没有缺陷,需要再次筛选 将可视化的图像更改后缀 更改为xml的 可视化代码 可视化后只有7000多个图像 原本的图像有1W多张 代码 # 按照xml文件删除对应的图片 # coding: utf-8 from P…...

el-tooltip内容换行显示
效果图: html: <div class"rules-tooltip flex-center"><el-tooltip class"item" effect"dark" placement"bottom-start"><div slot"content" v-html"tipsContent"></div>&l…...
linux 下用posix semaphore 解决资源竞争问题实例
/* author: hjjdebug date: 2023年 09月 20日 星期三 09:33:58 CST description: 10辆汽车通过承重5辆汽车的桥,处理一个资源争用问题 * 10个线程代表10辆汽车 * 桥上只能承载5辆汽车, 代表最大只能同时有5辆汽车通过 概要: 让10个线程竞争5个资源,用posix 接口, sem…...

RocketMQ —消费者负载均衡
消费者从 Apache RocketMQ 获取消息消费时,通过消费者负载均衡策略,可将主题内的消息分配给指定消费者分组中的多个消费者共同分担,提高消费并发能力和消费者的水平扩展能力。本文介绍 Apache RocketMQ 消费者的负载均衡策略。 背景信息 …...
Python自动化小技巧23——PDF文件拆分为单独页面(PyMuPDF)
其实编辑PDF用Adobe就行,它功能超级齐全,可是这玩意要收费...去弄免费破解版,找资源又得半天,所以用python来拆分PDF文件吧,可以批量化处理。 至于为什么不用WPS.....别问,问就是不想开会员。 脚本代码 先…...
CISSP学习笔记:通过原则和策略的安全治理
#第一章 通过原则和策略的安全治理 1.1 理解和应用机密性、完整性和可用性的 安全的主要目标,CIA三元组 机密性、完整性和可用性,每条原则的重要性主要取决于组织的安全目标以及安全性所受到的威胁程度 1.1.1 机密性 机密性:限制未授权主…...

【Java 进阶篇】数据定义语言(DDL)详解
数据定义语言(DDL)是SQL(结构化查询语言)的一部分,它用于定义、管理和控制数据库的结构和元素。DDL允许数据库管理员、开发人员和其他用户创建、修改和删除数据库对象,如表、索引、视图等。在本文中&#x…...

MySQL详细案例 1:MySQL主从复制与读写分离
文章目录 1. MySQL主从复制1.1 使用场景1.2 MySQL的复制类型1.3 主从复制的作用1.4 主从复制的工作过程1.5 实现MySQL主从复制1.5.1 前置准备1.5.2 主服务器mysql配置1.5.3 从服务器1 mysql配置1.5.4 从服务器2 mysql配置 1.6 MySQL主从复制延时问题的原因和解决办法1.6.1 故障…...

Kafka 常见问题
文章目录 kafka 如何确保消息的可靠性传输Kafka 高性能的体现利用Partition实现并行处理利用PageCache 如何提高 Kafka 性能调整内核参数来优化IO性能减少网络开销批处理数据压缩降低网络负载高效的序列化方式 kafka 如何确保消息的可靠性传输 消费端弄丢了数据 唯一可能导致…...

如何去开展软件测试工作
1. 软件测试 在一般的项目中,一开始均为手动测试,由于自动化测试前期投入较大,一般要软件项目达到一定的规模,更新频次和质量均有一定要求时才会上自动化测试或软件测试。 1.1. 项目中每个成员的测试职责 软件测试从来不是某一…...

详解如何在python中实现简单的app自动化框架
一、app自动化环境搭建 1、安装jdk及配置jdk的环境变量 app底层是c语言,应用层是java,所以需要jdk 2、安装SDK,配置android SDK环境 3、安装模拟器 4、下载安装Appium工具 01、appium客户端 appium destop 服务器 02、命令行安装&#…...

【TCP】三次握手 与 四次挥手 详解
三次握手 与 四次挥手 1. 三次握手2. 四次挥手三次握手和四次挥手的区别 在正常情况下,TCP 要经过三次握手建立连接,四次挥手断开连接 1. 三次握手 服务端状态转化: [CLOSED -> LISTEN] 服务器端调用 listen 后进入 LISTEN 状态ÿ…...

正则表达式新解
文章目录 是什么?正则用法匹配单个字符匹配一组字符其他元字符核心函数 贪婪匹配和非贪婪匹配正则练习 是什么? 正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊…...

MissionPlanner编译过程
环境 windows 10 mission planner 1.3.80 visual studio 2022 git 2.22.0 下载源码 (已配置git和ssh) 从github上克隆源码 git clone gitgithub.com:ArduPilot/MissionPlanner.git进入根目录 cd MissionPlanner在根目录下的ExtLibs文件下是链接的其它github源码࿰…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...

Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...