一个例子,带你了解神秘的 DataTransfer
关于 DataTransfer
在开发中,涉及到文件上传的场景比比皆是,尤其是在一些 2B、2G 的产品中,为了方便用户操作,许多项目在手动上传的同时还需要支持「 文件拖拽上传」,以此来提高用户体验。一说到「 文件拖拽上传」,我们就不得不提到 DataTransfer
对象。
DataTransfer
对象好比一个使者,他负责携带用户拖拉的文件,并将文件数据信息传递到用户最终拖放的地方。DataTransfer
业务范围很广,他可以携带一种或者多种数据,同时也支持一种或者多种的数据类型。除此之外,DataTransfer
还有一个很大的权力,他可以修改用户的拖拉数据,并且限制用户的行为,比如限制用户的拖放类型,详情可可以参考 DataTransfer
因此,了解 DataTransfer
是使用「 文件拖拽」的必修课。
一个例子看懂 DataTransfer
概述
描述:页面有一个文本输入框,我们可以将输入的文字存到 DataTransfer
中,并在蓝色区块拖放置黄色区块的时候,将文字写入黄色框中,而这些事情,都是通过 DataTransfer
来完成。
<div class="inputWrap">
<span>输入你的资料</span>
<input type="text" id="dragInput" />
</div>
<div class="dragWrap">
<div draggable="true" class="box box-dragger"></div>
<div droppable="true" class="box box-dropper"></div>
</div>

代码实现
当你拖动一个区块(文件)时,最先触发的是 dragstart
事件,因此,我们可以在 dragstart
触发的时候将输入框文字信息写入到 DataTransfer
中:
const dragger = document.querySelector(".box-dragger");
const dragInput = document.querySelector("#dragInput");
let dragTemp;
dragger.addEventListener("dragstart", (e) => {
dragTemp = e.target;
// 文字信息写入
});
在监听拖拽事件的时候要阻止 dragover
的默认行为,才能成功地触发 drop
事件,并将拖拽元素成功放入目标元素中
dropper.addEventListener("dragover", (e) => {
e.preventDefault();
});
使用 dataTransfer.setData 修改数据
dataTransfer 可以通过 setData(format, data)
来写入数据
dragger.addEventListener("dragstart", (e) => {
dragTemp = e.target;
e.dataTransfer.setData("text/plain", dragInput?.value ?? "");
});
使用 dataTransfer.getData 获取数据
dataTransfer 可以利用 getData(format)
读取拖拽数据,拖拽事件结束时,会触发 drop
事件,我们在这里读取刚才写入的数据,并放入拖放目标里面:
const dropper = document.querySelector(".box-dropper"); // 拖放目标
dropper.addEventListener("drop", (e) => {
// 数据读取
const dragText = e.dataTransfer.getData("text/plain");
dragTemp.style.margin = "10px";
dragTemp.style.width = "180px";
dragTemp.style.height = "180px";
dragTemp.append(dragText);
e.target.appendChild(dragTemp);
e.target.style.color = "#fff";
e.target.style.background = "#FFC48B";
dropper.style.border = "none";
});
对拖拽元素放入目标元素的过程做一些视觉上的交互
dropper.addEventListener("dragenter", (e) => {
dropper.style.background = "#d4965a";
dropper.style.border = "1px dashed #0a0a0a";
});
dropper.addEventListener("dragleave", () => {
dropper.style.background = "#FFC48B";
dropper.style.border = "none";
});
最终效果
以上例子,是绝大部分拖拽场景中需要使用到的,如果你动手实现得到了最终效果,你就已经开始了解了 DataTransfer
这个神秘的对象。接下来,我们聊聊它的属性和方法。
DataTransfer 对象属性和方法
DataTransfer 对象属性
DataTransfer.dropEffect
获取当前的拖放操作类型,或者设置当前的拖放操作类型。类型的值可能为: none
,copy
, link
或 move
。当设置不同的类型时,拖拽效果会有所不同,主要体现在拖放鼠标的样式上:

DataTransfer.effectAllowed
提供可能的所有类型的操作。操作类型可能为:
none
:不允许拖拽。鼠标保持禁止状态copy
:允许复制copyLink
:允许复制和链接copyMove
:允许复制和移动操作link
:允许在新位置建立链接linkMove
:允许链接和移动操作move
:允许将元素移动到新位置all
:允许任意操作uninitialized
:表示未初始化,效果和all
一样
effectAllowed
和 dropEffect
的区别:
effectAllowed
主要在dragstart
事件中使用,dropEffect
属性主要在dragenter
和dragover
事件中使用effectAllowed
会限制dropEffect
的值,dropEffect
属性只能设置effectAllowed
允许的值;举个简单的例子,如果设置effectAllowed
的值为link
,设置dropEffect
的值为copy
,两者不一致拖拉是无效的,没法响应drop
事件。
dragger.addEventListener("dragstart", (e) => {
e.dataTransfer.effectAllowed = "link";
});
// dropper
dropper.addEventListener("dragover", (e) => {
event.dataTransfer.dropEffect = "move";
});
但是大部分场景都是拖拉拽,所以这个属性用得并不多。
DataTransfer.files
拖拽的本地文件列表。如果拖动操作不涉及文件,则 files.length
为 0。除了拖拽,当用户复制文件、粘贴文件也能在 DataTransfer
中拿到文件数据。
DataTransfer.items(只读)
只读属性,用来获取拖拽的数据信息,它是 DataTransferItem
类型的数据集合数组。DataTransferItem
包含多个属性和方法,属性有 kind
和 type
,方法有 getAsString()
和 getAsFile()
DataTransfer.types(只读)
只读属性,由拖拽内容包含的类型组成的数组,我们可以通过遍历来查看拖拽内容包含的所有类型
DataTransfer 对象方法
DataTransfer.clearData([format])
对给定类型关联的数据进行删除
DataTransfer.getData(format)
返回给定类型的数据,如果该类型的数据不存在或数据传输不包含数据,则返回空字符串
DataTransfer.setData(format, data)
设置给定类型的数据。如果该类型的数据不存在,就在末尾添加。如果该类型的数据已存在,则在相同位置把现有数据替换掉
DataTransfer.setDragImage(img, xOffset, yOffset)
设置用于拖动的自定义图像,就是拖拽时候我们可以自定义一张图片跟在鼠标后面,属于视觉交互。其中img
表示自定义图片元素,offsetX
表示距离鼠标的水平偏移距离,offsetY
表示距离鼠标的垂直偏移距离
总结
开始遇到 DataTransfer
时,感觉这个对象神秘又陌生,但其实只要掌握它的几个主要属性,我们就能在绝大多数的场景中熟练使用,实现我们最终想要的效果。
最后,
很感谢你能看到这里,如果你觉得有收获的话,可以给我一个免费的赞哦!
参考
developer.mozilla.org/zh-CN/docs/… www.zhangxinxu.com/wordpress/2…
转载自:https://juejin.cn/post/7134638218074390559