拖放API基础

drag:被拖放元素 在拖拽的过程中触发

dragend 被拖放元素 拖拽完成时

dragenter 目标元素 拖放元素进入目标元素时

dragover 目标元素 拖放元素在目标元素上时

dragleave 目标元素 拖放元素在目标元素上离开

drop 目标元素 被拖放的元素在目标元素上同时鼠标放开触发的事件

注:需要阻止dragover的默认行为才会触发drop事件

被拖拽的元素上需要设置属性:draggable="true",才能被拖拽

被拖拽的元素有三个事件,分别是:dragstart开始拖拽、drag正在拖拽、dragend拖拽结束(鼠标抬起)

验证一下这三个事件:

drag

target

效果:

当鼠标点击被拖拽元素时,触发dragstart事件,输出’dragstart’;

拖拽过程中,触发drag事件,输出’drag’;

鼠标抬起,拖拽结束,触发dragend事件,输出’dragend’

目标元素可绑定的事件有:dragenter,dragover,dragleave,drop

验证一下前三个

dragenter事件以鼠标位置为准,当鼠标进入目标元素范围,触发dragenter;鼠标离开目标元素范围,触发dragleave,或者鼠标抬起,被拖拽元素完全离开目标元素范围

target.addEventListener('dragenter',function(){

console.log('dragenter');

})

target.addEventListener('dragover',function(){

console.log('dragover');

})

target.addEventListener('dragleave',function(){

console.log('dragleave');

})

鼠标点在被拖拽元素最左上角时,当鼠标移入target区域,dragenter才触发,鼠标未进入,被拖拽元素进入大半部分了,也还没有触发dragenter事件;

鼠标点在被拖拽元素右边部分时,当鼠标进入target区域,被拖拽元素仅有小部分进入target范围,就已经触发了dragenter事件;

鼠标离开target区域,触发dragleave事件,或者在target区域放开鼠标,触发dragleave事件

drop事件:

在上一个例子中可以看到,鼠标在target区域放开,自动触发的是dragleave事件,被拖拽元素回到原位置,没有保留在鼠标松开的位置,这时候需要解除dragover的默认行为(即dragleave),触发drop事件,允许放置文件

target.addEventListener('dragenter',function(){

console.log('dragenter');

})

target.addEventListener('dragover',function(e){

e.preventDefault();//取消dragover的默认行为

console.log('dragover');

})

target.addEventListener('dragleave',function(){

console.log('dragleave');

})

target.addEventListener('drop',function(){

console.log('drop');

})

可以看到,鼠标在target区域松开,触发的不再是dragleave事件,而是drop

然后我就可以操作dom元素,当把元素拖到trarget范围内并drop时,让这个元素留在target中

target.addEventListener('drop',function(){

this.appendChild(drag);

//此处的this指target,是target绑定的事件,当事件触发,由target执行相应的处理函数

})

效果:

如果我有两个需要拖拽的元素,就需要判断是哪个元素被拖过来了,然后将这个元素append到target下

这时候,就需要使用dataTransfer对象了

dataTransfer对象:

1.getData()向dataTransfer对象中存放数据

2.setData() 从dataTransfer对象中读取数据

var drag = document.getElementsByClassName('drag')[0],

drag2 = document.getElementsByClassName('drag2')[0],

target = document.getElementsByClassName('target')[0];

//被拖拽元素

drag.addEventListener('dragstart',function(e){

var dt = e.dataTransfer;

dt.setData('className',this.className);//这里的this指的是drag

})

drag2.addEventListener('dragstart',function(e){

var dt = e.dataTransfer;

dt.setData('className',this.className);

})

//目标元素

target.addEventListener('dragover',function(e){

e.preventDefault();//取消dragover的默认行为

})

target.addEventListener('drop',function(e){

var dt = e.dataTransfer;

var dataName = dt.getData('className');

this.appendChild(document.getElementsByClassName(dataName)[0]);

})

效果:

拖放小demo:把元素拖到目标位置删除,效果如下:

思路:给要删除的每个元素绑定dragstart事件,把索引值传到dataTransfer对象中,drop获取到这个索引值,找到对应dom元素,删除

注意:使用for循环绑定监听时,会构成闭包,遍历的i值不会立即传到dataTransfer中,只是累加,当触发dragstart事件时,i都是5

body,

ul,

li {

margin: 0;

padding: 0;

list-style: none;

}

li {

width: 100px;

height: 50px;

background: #ccc;

text-align: center;

line-height: 50px;

margin: 10px 0;

}

.target {

width: 300px;

height: 300px;

background: black;

color: #fff;

font-size: 20px;

}

  • item1
  • item2
  • item3
  • item4
  • item5

删除列表

在此基础上再增加一个小功能,当一个li覆盖到另一个li,这个li就换位置

这样每个li也是拖拽操作的目标了

注意:每次把li换位置,index也跟着变了,所以,要想获取新的index值,就需要另外寻找,不再是按顺序了