资讯专栏INFORMATION COLUMN

拖拽上传功能的实现及原理

beanlam / 3630人阅读

摘要:场景最近,小明遇到这样一种情况在网页中上传文件时偶尔页面会崩溃。小明仔细测试了这种情况,发现之前用的一个文件上传组件有一点缺陷,于是,小明决定自己手写一个,样式如下图一是没有上传文件时的样式,图二为上传文件后的样式。

场景

最近,小明遇到这样一种情况:在网页中上传文件时偶尔页面会崩溃。小明仔细测试了这种情况,发现之前用的一个文件上传组件有一点缺陷,于是,小明决定自己手写一个,样式如下:

图一是没有上传文件时的样式,图二为上传文件后的样式。虚线部分为放置区域,先来看代码:

html部分
{{ fileName }}
将文件拖拽至此,或
css部分
    * {
      font-size: 14px;
    }
    .drag-area {
      height: 200px;
      width: 300px;
      border: dashed 1px gray;
      margin-bottom: 10px;
      color: #777;
    }
    .uploader-tips {
      text-align: center;
      height: 200px;
      line-height: 200px;
    }
    .file-name {
      text-align: center;
      height: 200px;
      line-height: 200px;
    }
js部分
    new Vue({
      el: "#app",
      data () {
        return {
          fileName: "",
          batchFile: "",
          MAX_FILE_SIZE: 10 * 1000 * 1000
        }
      },
      methods: {
        // 点击上传
        chooseUploadFile (e) {
          const file = e.target.files.item(0)

          if (!file) return
          if (file.size > this.MAX_FILE_SIZE) {
            return alert("文件大小不能超过10M")
          }

          this.batchFile = file
          this.fileName = file.name

          // 清空,防止上传后再上传没有反应
          e.target.value = ""
        },
        // 拖拽上传
        fileDragover (e) {
          e.preventDefault()
        },
        fileDrop (e) {
          e.preventDefault()
          const file = e.dataTransfer.files[0] // 获取到第一个上传的文件对象

          if (!file) return
          if (file.size > this.MAX_FILE_SIZE) {
            return alert("文件大小不能超过10M")
          }

          this.batchFile = file
          this.fileName = file.name
        },
        // 提交
        uploadOk () {
          if (this.batchFile === "") {
            return alert("请选择要上传的文件")
          }

          let data = new FormData()
          data.append("upfile", this.batchFile)

          // ajax
        }
      }
    })
核心原理说明

dragover和drop事件

第一个要说的就是拖拽中的这两个事件,因为这两个事件撑起了拖拽上传的核心功能。
对于拖拽这个动作而言,有二个核心概念,一个是拖拽元素,还一个是放置目标。这里,我只讲放置目标上的事件,对于拖拽元素的事件,请自行查阅。

那对于放置目标,它有什么事件呢?如下:
当某个元素被拖动到一个有效的放置目标上(如上例中虚线区域)时,下列事件会依次发生:
(1) dragenter
(2) dragover
(3) dragleave 或 drop
只要有元素被拖动到放置目标上,就会触发 dragenter 事件(类似于 mouseover 事件)。紧随其后的是 dragover 事件,而且在被拖动的元素还在放置目标的范围内移动时,就会持续触发该事件。如果元素被拖出了放置目标,dragover 事件不再发生,但会触发 dragleave 事件(类似于 mouseout事件)。如果元素被放到了放置目标中,则会触发 drop 事件而不是 dragleave 事件。

对于本例来说,我们只需要关注dragover和drop事件。但是drop事件却有点调皮,你想监听它,还得进行一些处理,因为默认情况下,元素是不允许放置的,在拖动元素经过某些无效放置目标时,可以看到一种特殊的光标(圆环中有一条反斜线),表示不能放置。如下:

如果拖动元素经过不允许放置的元素,那无论用户如何操作,都不会发生 drop 事件。那怎么办呢?
我们可以重写 dragover 事件的默认行为,如上例代码中的e.preventDefault()
细心的同学可能要问了,那drop事件中也有e.preventDefault(),去掉行不行呢?大家可以自行试下。

dataTransfer 对象

可能这个对象看着有些陌生,但是它的作用可不小。比如,你拖动一个图片到目标区域,那目标区域怎么获取这个图片的信息呢?就靠它!它是事件对象的一个属性,用于从被拖动元素向放置目标传递字符串格式的数据。在本例中,我们可以通过它来获取拖动中的文件信息。

input的change事件

这个事件其实有坑的,它有这样一个特性,即:上传同一个文件,并不会触发change事件,即使该文件内容做过修改。
细思极恐!比如,用户要上传一个文档,但是拖拽到虚线区域后发现文档内容还需要修改下,他改完后再拖拽该文档,再提交到服务器,那么他上传到服务器的文档内容却是未修改之前的!
所以,我们需要代码e.target.value = ""来进行重置处理,这样,每次上传文件都会触发change事件。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/101843.html

相关文章

  • 全局拖拽上传文件(类似百度网盘)实现踩坑

    摘要:记录下,开发需求是实现一个类似百度网盘全局拖拽的功能兼容浏览器,以上。监听上的事件,显示拖拽的蒙层监听目标节点上的拖拽事件。 记录下,开发需求是实现一个类似百度网盘全局拖拽的功能,兼容浏览器,IE0以上。实现思路是,采用原声的拖拽事件。监听window上的dragenter事件,拖拽目标节点是fixed罩住页面的dropZone节点。 监听window上的dragenter事件,显示...

    shiguibiao 评论0 收藏0
  • vue-avatar-tailor,vue头像裁剪组件

    摘要:实现原理简单,纯技术处理图片,几乎不需要用到相关知识面向人群急于使用头像裁剪组件的同学。裁剪框初始宽高上传图片后,裁剪区将预设为最大裁剪范围。支持矩形裁剪目前九宫仅支持将图片裁剪为正方形,不能裁剪为矩形,该功能将在后续优化。 项目简介 本组件是vue下的头像裁剪组件,可以直接拷贝代码使用,无需安装依赖 使用九宫格进行裁剪,自由选择裁剪区域。 实时预览裁剪后效果。 可以将裁剪好的图片,...

    imccl 评论0 收藏0
  • 基于NodeReact图片上传组件实现

    摘要:常用的设置如下下的请求风格下的请求和不太一样,在正式的请求发出之前都会先发一个类型为的请求作为试探,只有当该请求通过以后,正式的请求才能发向服务端。所以服务端路由我们还需要处理这样一个请求注意该请求同样需要设置跨域。 写在前面 红旗不倒,誓把JavaScript进行到底!今天介绍我的开源项目 Royal 里的图片上传组件的前后端实现原理(React + Node),花了一些时间,希望对...

    cfanr 评论0 收藏0
  • Markcook 1.2,超轻开源markdown编辑器

    摘要:更新历史修复了无法导出中文文件的,增加了拖拽导入文件的功能。把编码对象作为参数传入,就可以生成一个可供下载的链接,下载的内容是完美的中文字符其他种类字符同样支持,代码如下保存为格式以上就是两个关键新功能的实现原理。 Markcook 1.2 showImg(https://imgly.net/img/AhB.jpg); 项目地址:https://github.com/jrainlau...

    BlackMass 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<