利用HTML5新特性实现拖拽交换表格单元格元素

利用HTML5新特性实现拖拽交换表格单元格元素

HTML5新特性:拖放

拖放

拖放(Drag 和 Drop)是很常见的特性。它指的是您抓取某物并拖入不同的位置。

拖放是 HTML5 标准的组成部分:任何元素都是可拖放的。

浏览器支持

表格中的数字指示了完全支持拖放的首个浏览器版本。
《利用HTML5新特性实现拖拽交换表格单元格元素》

HTML 拖放实例

下列是关于拖放的简单例子:

实例

<!DOCTYPE HTML>
<html>
<head>
<script> function allowDrop(ev) {  ev.preventDefault(); } function drag(ev) {  ev.dataTransfer.setData("text", ev.target.id); } function drop(ev) {  ev.preventDefault(); var data = ev.dataTransfer.getData("text"); ev.target.appendChild(document.getElementById(data)); } </script>
</head>
<body>

<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>

<img id="drag1" src="img_logo.gif" draggable="true" ondragstart="drag(event)" width="336" height="69">

</body>
</html>

实例网址:W3School TIY Editor

拖放事件详解

  1. 把元素设置为可拖放

    首先,为了把一个元素设置为可拖放,请把它的 draggable 属性设置为 true:

    <img draggable="true">
    
  2. 设置拖放的内容 – ondragstart 和 setData()

    然后,规定当元素被拖动时发生的事情。

    在上面的例子中,ondragstart 属性调用了一个 drag(event) 函数,规定拖动什么数据。

    dataTransfer.setData() 方法设置被拖动数据的数据类型和值:

    function drag(ev) { 
        ev.dataTransfer.setData("text", ev.target.id);
    }
    

    在本例中,数据类型是 “text”,而值是这个可拖动元素的 id (“drag1”)。

  3. 设置拖到何处 – ondragover

    ondragover 事件规定被拖动的数据能够被放置到何处。

    默认地,数据/元素无法被放置到其他元素中。为了实现拖放,我们必须阻止元素的这种默认的处理方式。

    这个任务由 ondragover 事件的 event.preventDefault() 方法完成:

    function allowDrop(ev) { 
        ev.preventDefault();
    }
    
  4. 进行放置 – ondrop

    当放开被拖数据时,会发生 drop 事件。

    在上面的例子中,ondrop 属性调用了一个函数,drop(event):

    function drop(ev) { 
        ev.preventDefault();
        var data = ev.dataTransfer.getData("text");
        ev.target.appendChild(document.getElementById(data));
    }
    
    代码解释:
    • 调用 preventDefault() 来阻止数据的浏览器默认处理方式(drop 事件的默认行为是以链接形式打开)

    • 通过 dataTransfer.getData() 方法获得被拖的数据。该方法将返回在 setData() 方法中设置为相同类型的任何数据

    • 被拖数据是被拖元素的 id (“drag1”)

    • 把被拖元素追加到放置元素中

项目实战运用

<table style="table-layout: fixed; line-height: 45px; font-size: 16px;" width="100%" border="1" cellpadding="4" cellspacing="0">
    <tr style="background-color: rgb(132 188 247); color: rgb(255, 255, 255); text-align: center;">
        <th>时间段</th>
        <th>星期一</th>
        <th>星期二</th>
        <th>星期三</th>
        <th>星期四</th>
        <th>星期五</th>
        <th>星期六</th>
        <th>星期日</th>
    </tr>
    <tr style="text-align: center;">
        <td>时间段</td>
        <td>……</td>
        <!-- 已省略不重要的部分,主要实现以下两个单元格的拖拽交换 -->
        <td>
            <div @drop="drop($event)" @dragover="allowDrop($event)" draggable="true" @dragstart="drag($event)" :id="test1.saturday.id">
                {
  {test1.saturday.user}}
            </div>
        </td>
        <td>
            <div @drop="drop($event)" @dragover="allowDrop($event)" draggable="true" @dragstart="drag($event)" :id="test1.sunday.id">
                {
  {test1.sunday.user}}
            </div>
        </td>
    </tr>
</table>
// 实现拖拽交换单元格内元素
function allowDrop(ev: any) { 
    ev.preventDefault();
}
// 拖动时触发
function drag(ev: any) { 
    ev.dataTransfer.setData("id", ev.target.id);
    ev.target.style.border = "1px solid yellow";
    ev.target.style.cursor = "pointer";
}
// 放下后触发
function drop(ev: any) { 
    ev.preventDefault();
    var data = ev.dataTransfer.getData("id");
    swapElements(document.getElementById(data), ev.currentTarget);
    ev.target.style.border = "1px solid yellow";
    ev.target.style.cursor = "pointer";
    // 发送交换请求
    axios.post('/apply/manager/arrange', { 
        "method": "exchange",
        "shiftFirstId": data,
        "shiftSecondId": ev.target.id,
    }).then((res: any)=>{ 
        if (res.code === 200) { 
            message.success(res.msg);
        } else { 
            message.error(res.msg);
        }
    })
}
// 交换元素
function swapElements(a: any, b: any) { 
    // 交换两个dom元素
    if (a == b) return;
    //记录父元素
    var bp = b.parentNode;
    var ap = a.parentNode;
    //记录下一个同级元素
    var an = a.nextElementSibling;
    var bn = b.nextElementSibling;
    //如果参照物是邻近元素则直接调整位置
    if (an == b) return bp.insertBefore(b, a);
    if (bn == a) return ap.insertBefore(a, b);
    if (a.contains(b)) { 
        //如果a包含了b
        return ap.insertBefore(b, a), bp.insertBefore(a, bn);
    } else { 
        return bp.insertBefore(a, b), ap.insertBefore(b, an);
    }
}

踩坑记录

  1. 因为需求要做到两个元素的拖拽交换,所以这两个元素都要设置draggable为true并绑定ondrop, ondragstart, ondragover事件。
  2. 在drop方法中,不能简单的用ev.target.appendChild(document.getElementById(data))来实现,如果用这种方法实际上是将元素1的内容追加到元素2的dom中,无法达到交换的效果。
  3. 也不能用ev.target.replaceChild(document.getElementById(data), ev.target.firstChild)来做互换,会出现bug。
    原文作者:阿澈279
    原文地址: https://blog.csdn.net/qq_43658537/article/details/120880748
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞