一、拖拽原理
一个典型的拖拽操作是这样的:用户选中一个可拖拽的(draggable)元素,并将其拖拽(鼠标不放开)到一个可放置的(droppable)元素,然后释放鼠标。
1.1 HTML5中的 drag 与 drop 事件
1.1.1 drag事件
首先思考如何实现拖,以及实现拖要解决哪些点?
1.选中的元素可以被拖拽
将要被选中元素的全局属性draggable(draggable 属性规定元素是否可拖动)设置为true。
2.被拖拽开始时希望发生什么(比如样式发生变化)
使用dragstart事件(当用户开始拖拽一个元素或选中的文本时触发)
3.拖拽过程中,希望发生什么
拖拽过程中共分为3个阶段,拖拽元素进入可放置区域,拖拽元素在可放置区域上方,拖拽元素离开可放置区域。以上分别对应3个拖拽事件:dragenter(当拖拽元素或选中的文本到一个可释放目标时触发)、dragover(当元素或选中的文本被拖到一个可释放目标上时触发(每 100 毫秒触发一次))、dragleave(当拖拽元素或选中的文本离开一个可释放目标时触发)。
4.拖拽结束时,希望发生什么
使用dragend事件(当拖拽操作结束时触发 (比如松开鼠标按键或敲“Esc”键))
1.1.2 drop事件
思考当拖拽结束后,实现放要解决的问题?
1.当被拖拽元素释放时,希望发生什么
使用drop事件(当元素或选中的文本在可释放目标上被释放时触发)
1.1.3 图解
在上述拖拽过程中,drag事件(当拖拽元素或选中的文本时触发)会在被拖拉的节点上持续触发(相隔几百毫秒)。
二、场景实现
2.2.1 列表拖拽——同一区域间不同元素的拖拽
-
给每个拖拽元素添加draggable属性。
-
当拖拽元素被拖动时,其dragstart事件被触发,此时,获取该拖拽元素的dom节点,同时使样式发生变化。
-
当拖拽元素被拖入到目标元素上时,此时需要监听目标元素。
-
由于浏览器默认行为,所有元素都不允许其他元素拖到其自身,所以需要在目标元素中阻止下默认行为,监听目标元素的dragover和dragenter事件,阻止默认事件。此时,拖拽元素就可以被拖入到目标元素上了。
-
同时,从拖拽元素进入到目标元素中,监听目标元素的dragenter事件,对比当前拖拽元素索引及目标元素索引的大小,判断是向上拖拽还是向下拖拽,然后将其插入到对应位置。
-
最后,当拖拽元素被释放时,监听其dragend事件,在此事件中,恢复拖拽元素的样式
2.2.2 列表拖拽——不同区域间元素的拖拽
-
给每个拖拽元素添加draggable属性。
-
当拖拽元素被拖动时,拖拽元素的dragstart事件触发时,此时,获取每个拖拽元素的dom节点,同时使样式发生变化。
-
当拖拽元素被拖入到对面侧的盒子中,此时需要监听对面侧的盒子。
-
由于浏览器默认行为,所有元素都不允许其他元素拖到其自身,所以需要在对面侧盒子中阻止下默认行为,监听对面侧盒子的dragover事件,阻止默认事件。此时,拖拽元素就可以被拖入到对面侧盒子了。
-
当拖拽元素被释放在了对面侧盒子区域时,监听对面侧盒子的drop事件,将当前拖拽元素推入到对面侧盒子区域。同时在个每个拖拽元素的dragend事件中恢复元素原本样式。
三、社区精选拖拽组件
四、总结
本文介绍了HTML5中的 drag 与 drop实现拖拽的基本原理及简单场景实现。拖拽场景在前端开发中应用颇多,其共同点是都能够用拖拽API实现,不同点却是千变万化的,拖拽业务的难点不在于如何实现拖拽效果,而在于与业务场景的结合,如网格、树形、级联、框选等拖拽场景需储备足够的前端知识和一定开发能力才能够完成。