1、前言
文件上传方式:点击上传、拖拽上传,这里我们只考虑拖拽上传的原理。
实现拖拽,就需要用到拖拽相关的事件(DragEvent),如:
// 可拖拽元素相关事件
dragstart:当用户开始拖拽元素或选择文本时触发;
drag:当用户拖动元素或选择的文本时触发,每几百毫秒就会触发一次;
dragend:当拖动操作结束(释放鼠标按钮或单击 escape 键)时触发;
// 可拖拽元素的放置区域相关事件
dragenter:当可拖拽的元素或选择的文本进入有效的放置区域时触发;dragleave:当可拖拽的元素或选择的文本离开有效的放置区域时触发;
dragover:在可拖拽的元素或选择的文本被拖进有效的放置区域时触发(每几百毫秒);
drop:在可拖拽的元素或选择的文本被放置到有效区域时触发;
2、拖拽选择图片
<div>
<!-- 由于原生的文件上传按钮太丑了,这里使用自定义按钮来触发文件选择器 -->
<button id="uploadBtn" type="button">选择文件</button>
<input
id="inputFile"
type="file"
name="file"
style="display: none;"
>
</div>
<!-- 拖拽元素放置区域 -->
<div class="dragArea" id="dropTarget"></div>
<script>
// 给自定义按钮绑定点击事件,并打开文件选择器
const inputFile = document.getElementById('inputFile');
const uploadBtn = document.getElementById('uploadBtn');
uploadBtn.addEventListener('click', () => {
inputFile.click();
});
const dropTarget = document.getElementById('dropTarget');
/**
* 在目标容器的dragover事件处理器中,必须调用event.preventDefault(),这样该元素才能够接受drop事件
* 使用【dataTransfer】来获取拖放操作的数据
**/
dropTarget.addEventListener('dragover', (event) => {
event.preventDefault(); // 阻止默认行为允许放置
// 设置当前选定的拖放操作类型
event.dataTransfer.dropEffect = 'move';
});
dropTarget.addEventListener('drop', (event) => {
event.preventDefault();
const files = event.dataTransfer.files;
// 接下来就可以写预览图片,发送ajax请求的业务逻辑啦
for (let file of files) {
}
})
// 预览图片方法
function readFile () {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (event) => {
resolve(event.target?.result);
};
reader.readAsDataURL(file);
})
};
</script>
注意:为确保 drop
事件始终按预期触发,应当 dragover
事件处理器中始终包含preventDefault()
调用;
你也绑定【dragenter】与【dragleave】事件,来控制可拖拽元素进入或离开有效放置区域时的样式。
拖拽结束后,文件选择器不会自动关闭,需要手动点击取消按钮来关闭它。
3、DragEvent.DataTransfer
DataTransfer
对象用于保存拖动并放下(drag and drop)过程中的数据。它可以保存一项或多项数据,这些数据项可以是一种或者多种数据类型。
dropEffect:指定当前拖放的操作类型,值必须为 none
, copy
, link
或 move;
files:包含数据传输中可用的所有本地文件的列表。如果拖动操作不涉及拖动文件,则此属性为空列表;
items:包含拖拽过程中所有的数据,比如文件、元素等等;
详见:https://developer.mozilla.org/zh-CN/docs/Web/API/DataTransfer