博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
拖拽上传功能的实现及原理
阅读量:6093 次
发布时间:2019-06-20

本文共 2982 字,大约阅读时间需要 9 分钟。

场景

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

clipboard.pngclipboard.png

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

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事件却有点调皮,你想监听它,还得进行一些处理,因为默认情况下,元素是不允许放置的,在拖动元素经过某些无效放置目标时,可以看到一种特殊的光标(圆环中有一条反斜线),表示不能放置。如下:

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

  • dataTransfer 对象

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

  • input的change事件

这个事件其实有坑的,它有这样一个特性,即:上传同一个文件,并不会触发change事件,即使该文件内容做过修改。

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

转载地址:http://himwa.baihongyu.com/

你可能感兴趣的文章
BABOK - 企业分析(Enterprise Analysis)概要
查看>>
Linux 配置vnc,开启linux远程桌面
查看>>
CentOS6.4关闭触控板
查看>>
React Native 极光推送填坑(ios)
查看>>
Terratest:一个用于自动化基础设施测试的开源Go库
查看>>
修改Windows远程终端默认端口,让服务器更安全
查看>>
扩展器必须,SAS 2.0未必(SAS挺进中端存储系统之三)
查看>>
Eclipse遇到Initializing Java Tooling解决办法
查看>>
while((ch = getchar()) != '\n')
查看>>
好程序员web前端分享JS检查浏览器类型和版本
查看>>
Oracle DG 逻辑Standby数据同步性能优化
查看>>
exchange 2010 队列删除
查看>>
「翻译」逐步替换Sass
查看>>
H5实现全屏与F11全屏
查看>>
处理excel表的列
查看>>
C#数据采集类
查看>>
quicksort
查看>>
【BZOJ2019】nim
查看>>
LINUX内核调试过程
查看>>
【HDOJ】3553 Just a String
查看>>