拖~
在js里面关于拖这个概念是完全没有的(except h5). 以前只能造一大堆的轮子,比如使用mousedown + mousemove + mouseup. 这3个事件结合起来实现复杂的UI操作。 现在,h5出了一个拖拽系列的事件,可以部分省去我们的劳动。
现在基本的理一下吧。
H5之拖拽系列
1.针对被拖动元素的事件有:
dragstart ,drag, dragend.
触发顺序为: dragstart(一次)--drag(移动时触发)--dragend(一次,拖拽结束触发)
2.针对放置目标上的事件有:
dragenter,dragover,dragleave||drop.
字面上其实就可以理解
当有元素被拖过来时,首先会触发dragenter事件,然后触发dragover事件,如果你的没有将拖动元素放下,而是移开则会触发dragleave事件。
否则会触发drop事件.
上面只是理论,如果你实践起来,你会发现。(MD~) 这根本不能用啊~ 所以说,实践才是检验真理的唯一标准。
其实拖拽里面还有一些坑
拖拽的坑
首先拖放元素上面需要设置为draggable 为 true. (默认为false) 然后才可以拖动了。
属性值 | 说明 |
---|---|
true | 内容可被拖动。 |
false | 内容不可被拖动。 |
auto | 内容执行默认的浏览器行为(图像、链接和被选中的文本可被拖动,其他元素不能) |
<div class="subject" draggable='true'></div>
但是上面的设置只能在IE10+以上运行。 如果想向下兼容IE9的话(IE8不考虑). 则需要在元素上绑定mouseDown事件,通过调用dragDrop()方法来进行兼容.
subject.addEventListener('mousedown',function(e){
subject.dragDrop();
},false);
哎~ 怎么说嘞, 其实这个拖拽是IE发明的,h5把他收录了并且做了些微创新(其实改动蛮大的). 但是h5新定义的一些属性在IE的低版本中不能实现(cao~ 都怪IE一开始没有提示更新的机制)
在拖放过程中,会产生一个dataTransfer的对象. 最基本的方法就两个一个是.setData()和.getData(); 这是所有浏览器都兼容的。
方法 | 说明 |
---|---|
clearData(format) | 清除以特定格式保存的数据 。 |
getData(format) | 从 dataTransfer 对象中读取指定类型的值,参数是 MIME 类型。 |
setData(format, data) | 为 dataTransfer 对象指定特定格式的数据,这些数据只能在 ondrop 处理程序中读取。 |
setDragImage(element, x, y) | 指定一个元素拖动发生时显示在光标下方,三个参数分别是要显示的 HTML元素和光标在显示元素中的x、y坐标。 |
addElement(element) | 如果想要让某个元素跟随被拖拽元素一同被拖拽,可使用该方法。由于只有FF实现了这个方法,我这里就不赘述了 |
其实上面真正能投入生产的只有getData和setData。因为我们的目的兼容是IE8+。 所以其他的方法,哎~ 不过说都说了也得介绍一下。
关于setData,IE只定义了“text”和“URL”两种有效的数据类型. 但是H5 将类型扩展为所有的MIME。 然而这也造成了兼容性的麻烦。 聪明的H5 为了 兼容IE(因为这个对象是IE发明的). 他在解析的时候会默认将“text”和“URL” 转为“text/plain”和“text/uri-list”.
这里再次阐明一下使用setData和getData事件的时机.
setData(); 只能在dragstart事件中使用
getData(); 只能在drop事件中使用。
其实也是废话了。如果要求对拖拽要求不高的话,只需要对拖拽设置一个dragstart事件就够了.
对于setDragImage这个方法,可以说一下。默认的话就是使用被拖拽元素本身,但是使用这个方法就可以自定义被拖放元素是HTML元素中的哪一个(也并没有什么卵用).
这是一个非常基本的例子:
拖拽实例
//html很简单
<div class="subject" draggable='true'></div>
<div class="container" ></div>
//看一下js代码(这里是es6的写法)
let subject = document.querySelector('.subject'),
container = document.querySelector('.container');
subject.addEventListener('dragstart',function(e){
let data = e.dataTransfer;
data.setData('text',"123");
data.addElement(container);
},false);
container.addEventListener('dragover',function(e){
e.preventDefault();
},false);
container.addEventListener('dragenter',function(e){
e.preventDefault();
},false);
container.addEventListener('drop',function(e){
let data = e.dataTransfer.getData('text');
this.innerHTML = data;
console.dir(data);
});
window.ondrop = function(e){
e.preventDefault();
}
如果你的文件是从外面引入的,浏览器默认会自动新打开一个网页来。 所以这里需要禁止掉浏览器的默认行为.
使用 e.preventDefault();
由于目标元素默认不会开启容器的功能,这里你需要使用
container.addEventListener('dragover',function(e){
e.preventDefault();
},false);
container.addEventListener('dragenter',function(e){
e.preventDefault();
},false);
这两段代码开启容器效果(记住两个都必须有).
此外dataTransfer 对象上还有几个属性.
Property | Description |
---|---|
dropEffect | 获取或设置被拖动元素能够执行哪中放置行为,不同的行为显示相应的光标。 |
effectAllowed | 表示允许拖动元素的哪种 dropEffect。 |
files | 返回被拖放文件的FileList对象。 |
types | 返回ondragstart事件中传递的数据类型的类似数组的集合。 |
来看一看里面有哪些设置值吧
dropEffect的属性值分别有
(1) none:不能放置拖动元素(除文本框以外所有元素的默认值);
(2) move:应该把元素移动到放置目标;
(3) copy:应该把拖动元素复制到放置目标;
(4) link:应该在放置目标上打开拖动元素(拖动元素必须是有 URL 的链接)。
而且现在可以使用dragzone来代替上面两个属性的设置.
effectAllowed的属性值分别有:
(1) uninitialized:被拖动元素没有设置放置行为;
(2) none:被拖动元素不允许有任何行为;
(3) copy:只允许 copy 值的 dropEffect;
(4) move:只允许 move 值的 dropEffect;
(5) copeLink:copy 和 link 值的 dropEffect;
(6) copeMove:copy 和 move 值的 dropEffect;
(7) linkMove:link 和 move 值的 dropEffect;
(8) all:允许任意 dropEffect。
不过感觉并没有什么卵用. 而且dropEffect必须在dropenter 事件中设置,effectAllowed必须在dropstart中设置。cao ~
现在可以在html里面直接设置.使用dragzone属性:
属性值 | 作用 |
---|---|
copy | 表示将允许的元素放到该元素上时,会将拖拽数据复制到目标元素上。 |
move | 表示将允许的元素放到该元素上时,会将数据移动到目标元素上。 |
link | 表示将允许的元素放到该元素上时,将链接数据到目标元素上。 |
举例 :
<div class="subject" draggable='true'></div>
<div class="container" dragzone="move" ></div>
总结一下吧,如果你有着热爱新技术的热情,不怕浏览器的SB,视死如归的兼容性。拖拽还是有非常大的用处的。
如果你的leader要求你兼容IE8+的话,拖拽什么的都去屎吧~ .不过,如果你不怕麻烦其实也可以写两份js, 一份给现代浏览器使用,一份给远古的IE用。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。