JavaScript 实现一个文件拖拽 demo-鼠标不能拖动文件

JavaScript 实现一个文件拖拽 demo-鼠标不能拖动文件

拖拽事件

我们知道鼠标事件有mouseenter mouseleave mousemove 等等,不同的事件可以帮助我们实现不同的效果和功能,那么拖拽上传在浏览器中有没有对应的事件呢?

浏览器拖拽事件

  1. drag:元素被拖拽时由被拖拽元素触发的事件,在整个拖拽过程中每隔一段极段的时间便会触发
  2. dragstart:元素开始被拖拽时触发的事件
  3. dragend:元素结束拖拽时触发的事件
  4. dragover:当拖拽元素进入被放置区域时频繁触发的事件
  5. dragenter:当拖拽元素进入被放置区域时触发的事件
  6. dragleave:当拖拽元素离开被放置区域时触发的事件
  7. drop:当拖拽元素被放置在放置区域时触发的事件

从这些事件中,我们可以知道浏览器的拖拽事件本身是针对页面上的元素的,有些网页上的元素可以被拖动放置到其他位置也是通过这些事件实现的

但是这些事件能不能用来完成我们的文件拖拽功能呢?答案是当然的了!

拖拽文件功能的实现

上面的 7 个事件中,前 3 个是针对被拖动的元素的,由于电脑中的文件本身在页面上并不存在,所以拖拽文件用不到这 3 个事件

既然已经大致明确了所需要用到的事件,那么我们就来实现这个功能,首先在页面上添加一个元素作为文件放置的区域

// drag.html
<style>
#drag {
width: 300px;
height: 200px;
border: 1px solid #000;
}
</style>
<div id="drag"></div>

然后为放置区域添加事件监听,这里需要考虑下我们到底要用哪个事件

由于拖拽文件最终是要放置到页面上的,所以我们可以使用 drop 事件

<script>
const drag = document.getElementById('drag')
drag.addEventListener('drop', drop)
function drop (e) {
e.preventDefault()
console.log(e)
}
</script>

到这里,一个拖拽放置文件的基本功能就实现了,打开浏览器,拖拽文件并放置后,会看到控制台打印出了当前的事件对象

这个事件对象中的属性dataTransfer包含了我们拖拽的文件的信息,通过dataTransfer.files我们可以获取到被拖拽进页面的文件列表,它是一个数组,每个元素都是一个文件,通过遍历我们可以获取到拖拽进页面的每一个文件,然后通过FileReader可以读取这些文件

以拖拽图片为例,可以这样改写代码

function drop (e) {
e.preventDefault()
// 读取文件列表
const files = e.dataTransfer.files
if (!files.length) return
// 获取列表的第一个文件
const file = files[0]
// 创建 FileReader 实例来读取文件
const fileReader = new FileReader()
fileReader.readAsDataURL(file)
fileReader.onload = (res) => {
// 将图片显示到页面上
drag.innerText = ''
const img = document.createElement(`img`)
img.setAttribute('src', res.target.result)
drag.appendChild(img)
}
}

然而实际使用中,我们可能会需要对文件的格式进行判断,在这里就不多说怎么判断了,感兴趣的小伙伴可以自己将 file 对象打印出来,在它的属性找找有没有哪个属性可以用来判断文件类型的

推荐阅读