drag'n'drop

drag'n'drop是HTML5时代装逼必备技能之一,API相关介绍参见强大的MDN,然而新功能总是有很多坑的,让我们来挖一挖。

首先简单描述一下整个流程:

  1. 给想要支持drag的元素(暂且叫做A)加一个draggable="true"的attribute。
  2. 拖拽开始时,A触发dragstart事件,如果这时执行event.preventDefault(),则停止拖拽。
  3. 在拖拽的过程中,拖拽所到之处的元素(把它叫做B)会触发dragenterdragover事件,事件中运行event.preventDefault()才能drop,否则是不会触发drop事件的。
  4. 拖拽结束时,如果可以drop,则在B上会触发drop事件。
  5. 最后在A上触发dragend事件。
drag'n'drop_第1张图片
dnd.png

这个流程中其实是有很多坑的,下面一点点地挖:

  1. 我们知道,很多时候,HTML元素的属性值与名字相同的时候可以省略值的部分,比如可以写成,然而,draggable="true"的值并不是draggable,所以是不能省的!
  2. dragstart事件中,我们通常需要记录一些被拖拽元素的信息,event本身有一个event.dataTransfer.setData(format, data)方法,但是只支持简单的DOMString类型数据,一般来说是不够用的,不如将相关数据另外保存到一个对象中。
    这个时候问题就来了:
    • 不写event.dataTransfer.setData(format, data),Chrome下正常,Firefox不能拖拽。
    • event.dataTransfer.setData('text/plain', ''),Chrome和Firefox正常,IE报错参数异常。
    • 改成event.dataTransfer.setData('text', ''),因为IE只支持formattext,这下Chrome、Firefox、IE都正常了,但是Vivaldi不能拖拽。
    • 最后改成event.dataTransfer.setData('text', 0),因为Vivaldi下data不能为空,终于兼容各大现代浏览器了。
  3. 然后到了dragenterdragover的部分,由于要不断验证数据来判断是否可拖拽,自然就选用了一个dragover事件,当数据合法时event.preventDefault(),然后在除IE以外的浏览器上都正常,而IE依然是不能drop的。最后查MSDN发现,IE需要dragenterdragoverevent.preventDefault()才可以drop。
  4. drop的时候也有个小坑,在Firefox上drop事件如果没有event.preventDefault(),则drop后会发生跳转,然后就没有然后了。
  5. 最后关于dragend有个奇异的小坑,如果你使用的是Windows,那么很有可能你安装了一些诸如QQ电脑管家之类的工具,然后你的浏览器就很有可能被搜狗搜索之类的工具强行插入了,于是一个拖拽结束,立即会打开一个新窗口进行搜索,这时就需要把dragend事件也event.preventDefault()

你可能感兴趣的:(drag'n'drop)