谈谈对JavaScript原生拖放的深入理解

  拖放(drag-and-drop,DnD)其实是两个动作——拖和放。所以,它涉及到两个元素。一个是被拖的元素,称为拖放源;另一个是要放的目标,称为拖放目标。本文将通过拆分这两个概念来详细介绍原生拖放

拖放源

  什么样的元素才是拖放源呢?

  HTML5为所有HTML元素规定了一个draggable属性,表示元素是否可以拖动

  图像和链接的draggable属性自动被设置成了true,而其他元素这个属性的默认值都是false

  [注意]必须设置draggable='true'才能生效,只设置draggable不起作用

  默认情况下,文本只有在被选中的情况下才能拖动,而图像和链接在任何时候都可以拖动。而其他元素则无法被拖放

<input value="文字可拖动"> <img alt="图像可拖动" src="https://files.cnblogs.com/files/xiaohuochai/zan.gif"> <a href="#">链接可拖动</a> <div>元素不可拖动</div>

  当为元素设置draggable属性后,普通元素也可以拖动

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

兼容

  IE9-浏览器不支持draggable属性,但可通过mousedown事件处理程序调用dragDrop()方法来实现拖动效果

<div></div> <script> test.onmousedown = function(){ this.dragDrop(); } </script>

  [注意]如果让firefox支持draggable属性,必须添加一个ondragstart事件处理程序,并在dataTransfer对象使用setData()方法来启动效果

拖放事件

  拖放源涉及到3个拖放事件。拖动拖放源时,依次触发dragstart、drag和dragend这3个事件

dragstart

  按下鼠标键并开始移动鼠标时,会在被拖放的元素上触发dragstart事件。此时光标变成“不能放”符号(圆环中有一条反斜线),表示不能把元素放到自己上面

drag

  触发dragstart事件后,随即会触发drag事件,而且在元素被拖动期间会持续触发该事件

dragend

  当拖动停止时(无论是把元素放到了有效的放置目标,还是放到了无效的放置目标上),会触发dragend事件

<div draggable="true">0</div> <script> var timer,i=0; test.ondragstart = function(){ this.style.backgroundColor = 'lightgreen'; } test.ondrag = function(){ if(timer) return; timer = setInterval(function(){ test.innerHTML = i++; },100) } test.ondragend = function(){ clearInterval(timer); timer = 0; this.style.backgroundColor = 'pink'; } </script>

拖放目标

  拖放目标是指被拖动的元素松开鼠标时被放置的目标

  拖放源被拖动到拖放目标上时,将依次触发dragenter、dragover和dragleave或drop这四个事件

dragenter

  只要有元素被拖动到放置目标上,触发dragenter事件

dragover

  被拖动的元素在放置目标的范围内移动时,持续触发dragover事件

dragleave

  如果元素被拖出了放置目标,触发dragleave事件

drop

  如果元素被放到了放置目标中,触发drop事件

  [注意]firefox浏览器的drop事件的默认行为是打开被放到放置目标上的URL。为了让firefox支持正常的拖放,还要取消drop事件的默认行为

  默认情况下,目标元素是不允许被放置的,所以不会发生drop事件。只要在dragover和dragenter事件中阻止默认行为,才能成为被允许的放置目标,才能允许发生drop事件。此时,光标变成了允许放置的符号

<div draggable="true">拖放源</div> <div>拖放目标</div> <script> var timer,i=0; var timer1,i1=0; //兼容IE8-浏览器 test.onmousedown = function(){ if(this.dragDrop){ this.dragDrop(); } } test.ondragstart = function(){ this.style.backgroundColor = 'lightgreen'; this.innerHTML = '开始拖动'; } test.ondrag = function(){ if(timer) return; timer = setInterval(function(){ test.innerHTML = '元素已被拖动' + ++i + '秒'; },1000); } test.ondragend = function(){ clearInterval(timer); timer = 0;i =0; this.innerHTML = '结束拖动'; this.style.backgroundColor = 'pink'; } target.ondragenter = function(e){ e = e || event; if(e.preventDefault){ e.preventDefault(); }else{ e.returnValue = false; } this.innerHTML = '有元素进入目标区域'; this.style.background = 'red'; } target.ondragover = function(e){ e = e || event; if(e.preventDefault){ e.preventDefault(); }else{ e.returnValue = false; } if(timer1) return; timer1 = setInterval(function(){ target.innerHTML = '元素已进入' + (++i1) + '秒'; },1000); } target.ondragleave = function(){ clearInterval(timer1); timer1 = 0;i1=0; this.innerHTML = '元素已离开目标区域'; this.style.backgroundColor = 'lightblue'; } target.ondrop = function(){ clearInterval(timer1); timer1 = 0;i1=0; this.innerHTML = '元素已落在目标区域'; this.style.backgroundColor = 'orange'; } </script>

dataTransfer对象

  为了在拖放操作时实现数据交换,引入了dataTransfer对象,它是事件对象的一个属性,用于从被拖动元素向放置目标传递字符串格式的数据

  dataTransfer对象有两个主要方法:getData()和setData()

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wzjjfs.html