H5 拖拽操作
前言
在原生H5中,可以通过提供的api实现在网页内元素的拖拽操作。相对于传统的写法更加的简单。
而想要实现拖拽,主要需要进行两个方面的工作,第一是给元素设置draggable='true'
属性,img和a标签是默认允许拖拽的。第二是编写拖拽相关的事件处理函数。
拖拽主要的过程
在整个拖拽的过程中,可以把行为分成两个部分,一部分是关于拖拽元素的操作,另外一个部分是关于拖拽元素最终放置的容器上的操作。
当拖拽元素时,拖拽事件执行的流程如下:
dragstart -> drag -> dragend
dragstart
事件的触发时机是在按住鼠标开始拖动的时候,只会触发一次。
drag
事件是在按住鼠标拖动的过程中触发,是属于持续触发的状态。
dragend
事件是在释放鼠标之后触发,此时无论是已经将目标放在了有效的位置还是放在了无效的位置上,都会触发这个事件。
放置元素主要经历的过程
当我们放置元素时,需要经历的事件变化流程如下:
dragenter -> dragover -> drop
dragenter
事件,当拖拽元素被拖拽到了目标元素上,就会被触发
dragover
事件,当拖拽的元素被拖拽到了目标元素上并且在目标元素上移动时,就会持续性的触发。
drop
事件,拖拽的元素放在了目标元素身上的时候会被触发。
tip: 这当中在
dragover
事件之后还包含了dragleave
事件,当元素离开了目标元素时触发。
整体的拖拽流程如下:
dragstart->drag->dragenter->dragover->dragleave->drop->dragend
例如:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style type="text/css"> .box { width:100px; height: 100px; background-color: lightblue; } #content { width:300px; height: 300px; border:2px solid #222; position: absolute; right:0; top:0; } </style> </head> <body> <div class="box" draggable='true'></div> <div id="content"></div> </body> <script type="text/javascript"> var box = document.getElementsByTagName('div')[0]; var content = document.getElementById('content'); box.ondragstart = function() { console.log(1111) event.dataTransfer.setData('Text',this.className); } box.ondrag = function() { console.log(2222) } box.ondragend = function() { console.log(3333) } content.ondragenter = function() { console.log('enter') } content.ondragover = function() { console.log('over') event.preventDefault(); } content.ondrop = function() { console.log('drop') var data = event.dataTransfer.getData('Text'); this.appendChild(document.getElementsByClassName(data)[0]) } </script> </html>
实现的效果:
tip: 想要顺利的完成拖拽,需要在
dragover
事件里阻止默认行为,event.preventDefault();
火狐的兼容问题
在火狐浏览器里,如果仅仅给元素设置draggable='true'
这个属性,是无法完成拖拽的[谷歌没有问题]。
要解决这个问题必须为拖拽元素绑定dragstart事件处理函数,并且在该函数中调用event.dataTransfer.setData函数
// box 是拖拽的元素 box.ondragstart = function() { console.log(1111) event.dataTransfer.setData('Text',this.className); }
同时,在火狐浏览器当中,当我们直接进行拖拽的时候,发现会产生打开新选项卡的现象,解决办法是在所有的容器代码里,都加上阻止默认行为的代码:
event.preventDefault(); event.stopPropagation();