最早在网页中引入JavaScript拖放功能的是IE4,当时网页只有两种对象可以拖放:图像的文本。在HTML5中提供了拖拽的API,使得任意元素都可以实现拖放,当我们在网页上拖放某个元素的时候将会依次触发以下事件:

1、ondragstart--开始拖动元素时触发

2、ondrag--按住左键,拖动元素时触发

3、ondragend--释放左键,结束拖动时触发

  当释放某个元素时将会依次触发以下时间:

1、ondragenter--拖动元素开始进入容器时触发

2、ondragover--拖动元素进入容器,拖动时触发

3、ondragleave--拖动元素离开容器时触发

4、ondrop--释放拖动元素时触发,优先ondragend触发

PS:在默认情况下,一个元素是不能放置到另一个元素里的,如果要实现拖放的功能,则需要在ondragover事件中需要加上event.preventDefault()阻止默认行为,否则ondrop就不会执行了

 

dataTransfer对象

  在实现拖放效果的时候并且要发生数据的变化,在IE5中引入了dataTransfer对象,它是事件对象的一个属性,用于拖动元素向容器传递字符串格式数据,使用这个对象的属性和方法可以用来完善拖放功能。

  dataTransfer对象有两个主要方法:getData()和setData()。getData()用于获取setData()保存的值。setData()方法的第一个参数也是getData()方法唯一的一个参数,为字符串类型,表示保存的数据类型,在IE中指定义了'text'或者'URL'两种有效类型,而在HTML5中是允许指定各种MIME类型,这两种类型会被映射为'text/plain'和'text/uri-list',用法如下:



//设置和接收字符串
    event.dataTransfer.setData('text/plain','some text');
    var text = event.dataTransfer.getData('text/plain');
    
    //设置和接收URL
    event.dataTransfer.setData('text/uri-list','');
    var url= event.dataTransfer.getData('text/uri-list');



   实际上,dataTransfer对象可以为每种MIME类型保存一个值,就是说可以同时在对象上保存一段文本和一段URL,保存在对象中的数据只能在drop时间处理程序中去读取了。

  利用dataTransfer对象不光能够传输数据,还能通过它来确定被拖动元素以及作为放置的目标的元素能接受什么操作,需要访问:dropEffect和effectAllowed这两个属性,具体可以查一下API哈。

 

  好了,有了以上的知识前提下,我写了一个简单的demo,代码如下:



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .interest-box{
            width: 300px;
            height: 100px;
            border:1px solid #eee;
            list-style: none;
        }
        .interest-box li{
            width: 50px;
            line-height: 30px;
            border-radius: 5px;
            border:1px solid #1d7db1;
            text-align: center;
            float:left;
            margin-right: 10px;
            cursor: pointer;
            -webkit-user-select: none;
        }
        #trash{
            width: 100px;
            height: 100px;
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<p>选择自己的兴趣爱好</p>
<ul class="interest-box">
    <li class="interest" draggable="true">音乐</li>
    <li class="interest" draggable="true">运动</li>
    <li class="interest" draggable="true">电影</li>
    <li class="interest" draggable="true">code</li>
</ul>
<p>我的兴趣:</p>
<ul id="my-interest" class="interest-box"></ul>
<p>垃圾桶</p>
<div id="trash"></div>
<script>
    window.onload = function(){
        var $li = document.getElementsByTagName('li'),
                $mi = document.getElementById('my-interest'),
                $trash = document.getElementById('trash');
        for(var i= 0,length = $li.length;i<length;i++){
            //为每个li添加ondragstart事件
            $li[i].ondragstart = function(e) {
                //存储innerHTML
                e.dataTransfer.setData('text/plain','<li>'+ e.target.innerHTML);
            }
        }
        $mi.ondragover = function(e){
            //阻止默认行为
            e.preventDefault();
        }
        $mi.ondrop = function(e){
            //获取数据
            var html = e.dataTransfer.getData('text/plain');
            if(html.indexOf('<li>')==0){
                var _li = document.createElement('li');     //创建新元素
                _li.id = (new Date()).getTime();            //生成唯一ID
                _li.draggable = true;
                _li.innerHTML = html.substring(4);          //字符串截取
                $mi.appendChild(_li);
                //添加ondragstart
                _li.ondragstart = function(e){
                    e.dataTransfer.setData('text/plain','<id>'+_li.id);
                }
            }
        }
        $trash.ondragover = function(e){
            //阻止默认行为
            e.preventDefault();
        }
        $trash.ondrop = function(e){
            var _id = e.dataTransfer.getData('text/plain');
            if(_id.indexOf('<id>')==0){
                var target = document.getElementById(_id.substring(4));
                $mi.removeChild(target);        //删除节点
            }
        }
    }
</script>
</body>
</html>


 截图如下:



 

最后查了一下拖放在各大浏览器的支持情况,在IE8往后都是部分支持,在实际项目中我也没有做过拖放的需求,不是很清楚支持的情况,而在手机端就全军覆没了呢

如果文中出现错误,欢迎大家指正:)