HTML5 Drag & Drop 入门

以前在面试的时候正好做过一道拖动方块的题,那个时候没有用 HTML5 的 Drag & Drop 来做,其实用 Drag 来做的话会简单很多,不过当时写的文件现在估计早就找不到了,这次业务正好有这个需求,而且又不用考虑兼容性,理所当然的用起了这个。

Drag 的使用门槛还是相当低的,基本上只要知道什么时候触发什么事件就行了,因此这篇主要也像是过一遍 API。

用原生 JS 实现了以下效果:

当然以上实现还有一些问题,比如说从 A 到 B 是无法直接拖曳到第一位的,自己实现的数据和 DOM 之间的关联关系似乎也不是很靠谱,后来在 Vue 中实现了一个类似的功能就方便多了。

首先,初始化,我们把数据和 DOM 之间的关系建立在初始化和改变中,通过数据生成 DOM ,通过 DOM 的 index 去找到对应的 item。

我们要求列表的每一项都是可拖动的,所以每个 li 元素的 draggable="true"。(因为 Vue 习惯了当时写了 draggable 于是没有生效……)

然后注册事件,事件我们统一的绑定在面板(panel)上,利用事件冒泡的效果比较好一点,虽然在数量比较少的情况下其实是无所谓的。(不过一个多月之前做了一个微小的实验,千条绑定了三个事件在移动端卡卡卡卡……使用冒泡处理就没有这么多烦恼)

对于要进行拖曳的数据,我们绑定 drag(包括了从 dragstartdragend 一系列),对于目标位置,我们使用 drop 来处理拖曳放置的结果,特别的是 dragover 是用于允许 drop 的,需要避免浏览器的默认事件,需要做 preventDefault() 处理。

在所有事件中,我们都能从 event.dataTransfer 中存取 data,操作方式和其他存储结构并没有什么本质的区别,并且只能是 String。这里我们为了实现 DOM 和 数组的关联存了一些必须品。

drop 中,就只剩下插入 DOM 和交换数据两个主要职能了。写完这个之后发现了一个叫做 Element.insertAdjacentHTML(),深表 Amazing。当时用的还是很 Low 的 insertBeforeappendChild,所以交互并不是很好。

当然,实际的需求比这个简单很多,顺便也好久没写 ES5 了,写着写着不小心就会变成 ES6 (笑)。

其实这篇博客也拖了好多天,上班之后总觉得通勤很辛苦,一回家就马上咸鱼了,本来想在 Vue 上也抽象一个出来,但是最近需求比较多,一直后延这个东西的优先级,于是乎至今还没一个 demo……咳咳。

参考资料 & 扩展阅读:

标签: 知识, 代码段, 语法, html5

添加新评论