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

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

说在前面

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

效果展示

体验地址: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 = "";
});
阻止浏览器默认行为,例如打开文件

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

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即可监听元素的拖拽事件。

<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);
    }
}
获取到上传文件并传递给父组件

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

uploadFile(file) {
    this.$emit("uploadFile", file);
}
组件完整代码

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

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

源码

组件体验及文档地址:http://jyeontu.xyz/jvuewheel/#/JDragUploadView

Gitee源码:https://gitee.com/zheng_yongtao/jyeontu-component-warehouse/tree/master/JYeontuComponentWarehouse/packages/JDragUpload

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。

目录
相关文章
|
8月前
|
移动开发 监控 开发者
webuploader上传插件源代码重点难点分析
WebUploader 是一个基于 HTML5 的文件上传插件,提供了多种功能和交互方式,支持拖拽、选择文件、分片上传、图片预览、上传进度等特性。它兼容主流浏览器,并且能够应对复杂的上传需求,如大文件上传和断点续传。 在分析 WebUploader 的源代码时,重点可以放在文件上传的核心功能、事件管理、拖拽上传、进度显示、分片上传的实现方式等方面。 以下是对 WebUploader 源代码的重点和难点的分析。
296 4
|
4月前
|
人工智能 API 调度
我用 n8n 教自动化,结果自己在干最蠢的活
作者本为学员免费开通n8n账号,却因频繁手动操作陷入效率困境。起初尝试全自动流程,反被滥用;最终引入“人在回路”(HITL)机制,结合自动化与人工审核,用飞书审批实现高效协作。真正高效的自动化,是让机器处理重复工作,人类专注核心决策。
|
5月前
|
人工智能 供应链 数据挖掘
智能体来了+智能体成企业转型新引擎,阿里云助力产业迈向智能化未来
智能体正成为企业转型新引擎,阿里云引领产业智能化。通过融合大模型与企业场景,智能体已实现降本增效、自动化办公、精准决策,广泛应用于制造、服务、零售等领域。2024年被视为“智能体应用元年”,阿里云推动技术普惠,助力企业AI转型,培育开发人才,开启智能经济新时代。(238字)
383 2
|
前端开发 JavaScript API
前端 JS 经典:阿里云文件上传思路
前端 JS 经典:阿里云文件上传思路
374 0
|
JavaScript API UED
Vue3使用触摸滑动插件(Swiper)
本文介绍如何在Vue2项目中使用Swiper插件实现触摸滑动功能,并封装了两种轮播图展示形式:首页轮播图(`type: banner`)和走马灯轮播图(`type: carousel`),以及信息展播模式(`type: broadcast`)。支持自定义轮播图片、区域尺寸、动画效果等属性。通过示例代码展示了不同切换动画及自定义效果,并提供了在线预览。适用于多种应用场景,提升用户体验。
1030 1
Vue3使用触摸滑动插件(Swiper)
|
存储 前端开发 Java
Element el-upload 文件上传/图片上传/拖拽上传/附带参数/附带请求头部详解
文目录 1. 前言 2. 基本用法 2.1 前端部分 2.2 后端部分 2.3 获取后端返回信息 3. 外观功能介绍 3.1 拖拽上传 3.2 显示图片 3.3 设置文件列表样式 3.4 显示提示信息 4. 事件功能介绍 4.1 限制上传文件数量 4.2 限制上传文件类型和大小 4.3 移除文件处理 4.4 手动上传 5. 附带参数 6. 附带请求头部 7. 小结
8157 0
|
JavaScript 前端开发 Java
Node 中的 AsyncLocalStorage 的前世今生和未来(二)
作者系统详实的介绍了什么是AsyncLocalStorage、如何使用、Node 是如何实现的 AsyncHook等。不论你是0基础还是对此API有些了解的读者都比较适合阅读此文。(文末有活动)
|
小程序 JavaScript
微信小程序之input组件及其获取用户输入信息
微信小程序之input组件及其获取用户输入信息
383 2
|
数据采集 监控 数据挖掘
打造高效用户旅程:埋点分析系统的实操指南
在数字化时代,了解用户如何与我们的产品或服务互动是至关重要的。用户行为,在广义上,指的是用户在网站、应用程序或其他数字界面上的所有动作和反应。这些行为可能包括点击链接、浏览页面、填写表单,甚至是在社交媒体上分享内容。每一个动作都是用户体验的一部分,并对我们理解他们的需求和偏好提供了宝贵的线索。 在技术层面上,用户行为的跟踪和分析可以让我们深入了解用户的互动模式,从而指导我们的产品改进和市场战略。通过分析这些数据,我们可以发现用户旅程中的关键触点,识别用户体验的痛点,以及揭示潜在的优化机会。这不仅有助于提升用户满意度和忠诚度,还可以增强产品的市场竞争力。
打造高效用户旅程:埋点分析系统的实操指南
|
JSON JavaScript 定位技术
Echarts自定义地图显示区域,可以显示街道,小区,学校等区域
Echarts自定义地图显示区域,可以显示街道,小区,学校等区域

热门文章

最新文章