HTML5拖放API Drag and Drop

此文研究Web API中的拖放接口,提供各个属性和方法的说明,解决拖放过程当中的拖拽数据对象存储和获取问题。html

拖放API做用到两个目标对象,分别是拖拽目标对象和放置目标对象。segmentfault

拖拽目标

一个设置draggable属性的值为trueDOM元素或者一个选中状态的文本区块能够成为拖拽目标。数组

<div draggable="true"></div>

OR
yy 20170629201338app

放置目标

一个绑定了下图放置目标对应的5个事件的DOM元素能够成为放置目标。函数

事件

拖放API有8个事件,其中有3个事件绑定在拖拽目标上,有5个事件绑定在放置目标上。spa

绑定在拖拽目标

Evnet Description
dragstart 当用户开始拖拽一个元素或者一个文本选取区块的时触发。
drag 当用户正在拖拽一个元素或者一个文本选取区块的时触发。
dragend 当用户结束拖拽一个元素或者一个文本选取区块的时触发。(如放开鼠标按键或按下键盘的 escap 键)

绑定在放置目标

Event Description
dragenter 当一个元素或文字选取区块被拖曳移动进入一个有效的放置目标时触发。
dragover 当一个元素或文字选取区块被拖曳移动通过一个有效的放置目标时触发。
dragleave 当一个元素或文字选取区块被拖曳移动离开一个有效的放置目标时触发。
dragexist 当一个元素再也不是被选取中的拖曳元素时触发。(Firefox能触发,触发顺序:dragexist->dragleave->drop;Chrome没法触发)
drop 当一个元素或文字选取区块被放置至一个有效的放置目标时触发。

经过下图能更直观观察每一个事件触发的时机.net

dragdrop-events

戳我看源码3d

注意:在dragover事件中使用event.preventDefault();阻止默认事件,才能触发drop事件code

DataTransfer对象

在进行拖放操做时,会触发上面所述的8个事件,每一个event事件对象中都会有DataTransfer对象用来保存被拖动的数据。它能够保存一项或多项数据、一种或者多种数据类型。htm

effectAllowed

用来指定拖动时被容许的效果。

dragstart事件中设置

属性

dropEffect

设置实际的放置效果,它应该始终设置成effectAllowed的可能值之一 。

dragenter事件和dragover事件中设置

effectAllowed和dropEffect属性的栗子:戳我看源码

files

包含一个在数据传输上全部可用的本地文件列表。若是拖动操做不涉及拖动文件,此属性是一个空列表。

filesZoneEl.addEventListener("drop", (event) => {
    event.preventDefault();
    let files = event.dataTransfer.files;
    for (let i = 0, len = files.length; i < len; i++) {
        let liEl = document.createElement("li");
        liEl.innerHTML = files[i].name;
        filesListEl.appendChild(liEl);
    }
});

drag-file

戳我看源码

types

保存一个被存储数据的类型列表做为第一项,顺序与被添加数据的顺序一致。若是没有添加数据将返回一个空列表。

items

存储DataTransferItem数据对象的列表。

方法

addElement()

设置拖动源。

event.dataTransfer.addElement(element);

setData()

为一个给定的类型设置数据并存储在items属性中。

getData()

items属性中获取给定类型的数据,无数据时返回空字符串。

event.dataTransfer.getData(type);

clearData()

items属性中删除与给定类型关联的数据,若类型为空则删除全部数据。

event.dataTransfer.clearData(type);

setDragImage()

自定义一个指望的拖动时的图片,默认为被拖动的节点。

event.dataTransfer.setDragImage(imgElement, offsetX, offsetY);
Param Description
imgElement 要用做拖动反馈图像元素。
offsetX 图像内的水平偏移量。
offsetY 图像内的垂直偏移量。

设置拖动时的图片时,要把图片预加载,不然图片会在拖动开始dragstart事件触发时才会加载图片,会致使拖动图出不来或闪一下的后果。可把图片放到<img>标签并设置display:none;,原理详看我以前的文章Web图片资源的加载与渲染时机

drag-imgage

DataTransferItemList

dataTramsfer对象的items属性,包含了一系列DataTransferItem拖拽数据对象。

属性

length

数组长度。

方法

add()

增长一个拖拽数据对象到items属性中,并返回增长的拖拽数据对象。

event.dataTransfer.items.add(file);

remove()

items属性中移除指定位置的一个拖拽数据对象。

event.dataTransfer.items.remove(index);

clear()

清空items属性中的所拖拽数据对象。

event.dataTransfer.items.clear();

DataTransferItem

DataTransferItemList列表中的拖拽数据对象。

属性

kind

拖拽数据对象类型。

Value Description
file 文件类型。
string 文本字符串类型。

type

MIME类型的Unicode字符串,例如text/plaintext/htmlimage/png

方法

getAsFile()

若拖拽数据对象是文件类型,则返回一个文件对象。

let itemList = event.dataTransfer.items;
for (let i = 0, len = itemList.length; i < len; i++) {
    if (itemList[i].kind == "file") {
        console.log(itemList[i].getAsFile());
    }
}

getAsString()

若拖拽数据对象是文本字符串类型,经过回调函数获取拖拽数据中的字符串数据。

let itemList = event.dataTransfer.items;
for (let i = 0, len = itemList.length; i < len; i++) {
    if (itemList[i].kind == "string") {
        itemList[i].getAsString((data) => {
            console.log(data);
        });
    }
}

拖放对象的数据存储

在进行拖放操做时,有可能须要把拖拽目标的数据传送给放置目标,此时通常操做是在dragstart事件触发时把须要的数据存储到一个变量,而后再drop事件触发时获取这个变量。但当dragstart事件和drop事件在不一样的文件定义,又不想玷污全局变量的状况下,咱们须要更好的办法来存储拖放数据。

DataTransfer对象中的items属性就是用来存储拖放数据的,数据类型分为文本类型和文件类型。

存储文本字符串类型数据:

event.dataTransfer.setData(type, data);

OR

event.dataTransfer.items.add(data, type);

一种文本字符串类型只能存储一个数据,当重复文本字符串类型存储数据时,后者会覆盖前者。

存储文件类型数据:

event.dataTransfer.items.add(file);

获取全部文本字符串类型的拖拽数据对象

event.dataTransfer.types

获取全部文件类型的拖拽数据对象

let files = event.dataTransfer.files;
for (let i = 0, len = files.length; i < len; i++) {
    console.log(files[i]);
}

OR

let itemList = event.dataTransfer.items;
for (let i = 0, len = itemList.length; i < len; i++) {
    if (itemList[i].kind == "file") {
        console.log(itemList[i].getAsFile());
    }
}

获取全部文本字符串类型的拖拽数据对象

let itemList = event.dataTransfer.items;
for (let i = 0, len = itemList.length; i < len; i++) {
    if (itemList[i].kind == "string") {
        itemList[i].getAsString((data) => {
            console.log(data);
        });
    }
}

获取指定文本字符串类型的拖拽数据对象

event.dataTransfer.getData(type);

删除指定文本字符串类型的拖拽数据对象

event.dataTransfer.clearData(type);

删除指定位置的拖拽数据对象

event.dataTransfer.items.remove(index);

清空全部拖拽数据对象

event.dataTransfer.clearData();

OR

event.dataTransfer.items.clear();

栗子

上面的几个栗子都使用了以上方法存储和获取拖拽数据对象,感兴趣的能够看看源码。

欢迎关注:Leechikit
原文连接:segmentfault.com

到此本文结束,欢迎提问和指正。写原创文章不易,若本文对你有帮助,请点赞、推荐和关注做者支持。

相关文章
相关标签/搜索