实现列表拖拽排序

描述:使用h5新增的拖拽属性draggable实现多个列表各自拖拽排序功能,多个列表之间互不影响。拖拽过程元素实时更新,交换位置。松开鼠标后得到拖拽前索引和拖拽后索引,根据索引对数据源进行更新。
使用的事件介绍
onmousedown:鼠标按钮在元素上按下时触发
onmouseup:在元素上松开鼠标按钮时触发
ondragenter:元素被 拖拽到 绑定该事件的元素范围内就触发
ondragover:鼠标移动时 , 元素在绑定该事件的元素范围内就会触发(非常频繁 , 影响性能 , 所以一般会阻止其默认事件e.preventDefault(),添加该事件可以给鼠标小手携带拖拽图标)
ondragend:拖拽结束

在这里插入图片描述

html

<p class="title">列表一</p>
<ul>
  <li>
    <span class="drag">1</span><span>文本一</span>
  </li>
  <li>
    <span class="drag">2</span><span>文本二</span>
  </li>
  <li>
    <span class="drag">3</span><span>文本三</span>
  </li>
  <li>
    <span class="drag">4</span><span>文本四</span>
  </li>
  <li>
    <span class="drag">5</span><span>文本五</span>
  </li>
  <li>
    <span class="drag">6</span><span>文本六</span>
  </li>
  <li>
    <span class="drag">7</span><span>文本七</span>
  </li>
  <li>
    <span class="drag">8</span><span>文本八</span>
  </li>
  <li>
    <span class="drag">9</span><span>文本九</span>
  </li>
</ul>
<p class="title">列表二</p>
<ul></ul>
<p class="title">列表三</p>
<ul>
  <li>
    <span class="drag">1</span><span>aaa</span>
  </li>
  <li>
    <span class="drag">2</span><span>bbb</span>
  </li>
  <li>
    <span class="drag">3</span><span>ccc</span>
  </li>
</ul>
<p class="title">列表四</p>
<ul>
  <li>
    <span>1</span><span>111</span>
  </li>
  <li>
    <span>2</span><span>222</span>
  </li>
  <li>
    <span>3</span><span>333</span>
  </li>
  <li>
    <span>1</span><span>444</span>
  </li>
  <li>
    <span>2</span><span>555</span>
  </li>
  <li>
    <span>3</span><span>666</span>
  </li>
</ul>

css

<style>
    * {
        padding: 0;
        margin: 0;
    }
    ul {
        border: 1px solid hotpink;
        padding: 10px;
        margin: 20px;
    }
    li {
        width: 300px;
        height: 20px;
        border: 1px solid #333;
        border-radius: 2px;
        margin: 10px 20px;
        list-style: none;
        /* text-align: center; */
        display: flex;
    }
    .drag {
        cursor: pointer;
    }
    span:nth-child(1) {
        flex: .4;
        background-color: skyblue;
    }
    span {
        text-align: center;
    }
</style>

js

<script>
  // 为需要拖拽的表格添加事件
  let uls = document.querySelectorAll('ul')

  // 当前拖拽所在ul的索引
  let dragUlIndex = null
  // 当前拖拽dom
  let dragLiTagger = null
  // 当前拖拽dom的索引
  let dragLiIndex = null
  // 被拖入dom的索引
  let enterLiIndex = null

  for (let ulIndex = 0; ulIndex < uls.length; ulIndex++) {
    let ulItem = uls[ulIndex];
    let lis = ulItem.children

    // 列表为空 || li标签不需要拖拽效果的不处理
    if (lis.length === 0 || !ulItem.children[0].children[0].className.includes('drag')) continue;

    // console.log(`第${ulIndex + 1}个表格可拖拽`);

    fn(ulItem, ulIndex, lis)

  }
  function fn(ulItem, ulIndex, lis) {
    for (let liIndex = 0; liIndex < lis.length; liIndex++) {
      let li = lis[liIndex]
      let dragDom = lis[liIndex].children[0]
      // 只对索引列添加拖拽效果
      dragDom.onmousedown = function () {
        li.setAttribute('draggable', true)
        dragUlIndex = ulIndex
        dragLiTagger = li
        // 存储当前拖拽列索引
        dragLiIndex = Array.from(lis).indexOf(dragLiTagger)
      }
      dragDom.onmouseup = function () {
        li.setAttribute('draggable', false)
      }
      li.ondragenter = function () {
        // 拖拽到其他列表不处理
        if (dragUlIndex !== ulIndex) return

        // 存储当前拖拽dom的索引和被拖入dom的索引
        let dragLiIndex = Array.from(lis).indexOf(dragLiTagger)
        enterLiIndex = Array.from(lis).indexOf(li)

        // 在当前dom上反复左右拖拽不处理
        if (dragLiIndex === enterLiIndex) return

        // console.log('拖拽在同一个ul中')
        // console.log({
        //   '拖拽元素': dragLiTagger,
        //   '拖拽元素索引': dragLiIndex,
        //   '被拖入元素': li,
        //   '被拖入元素索引': enterLiIndex
        // })

        if (dragLiIndex < enterLiIndex) {
          // 前面的dom拖到后面
          ulItem.insertBefore(dragLiTagger, li.nextElementSibling)
        } else if (dragLiIndex > enterLiIndex) {
          // 后面的dom拖到前面
          ulItem.insertBefore(dragLiTagger, li)
        }

      }
      li.ondragover = function (e) {
        e.preventDefault()
      }
      li.ondragend = function () {
        dragLiTagger.setAttribute('draggable', false)
        if (enterLiIndex === null || dragLiIndex === enterLiIndex) return
        // 有拖拽变化
        console.log({
          '拖拽ul': ulIndex,
          '拖拽前索引': dragLiIndex,
          '拖拽后索引': enterLiIndex
        })
        console.log('可更新数据')
        // 根据拖拽前后的索引, 对数据进行更新

        enterLiIndex = null
      }
    }
  }
</script>
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现列表排序的方法有很多种,这里介绍一种基于HTML5的API实现的方法。 首先,需要用HTML的table标签创建一个表格,每行作为一个项。然后,在每个表格行中添加一个`draggable="true"`属性来启用功能。接着,给每个表格行添加`ondragstart`和`ondragover`事件处理程序。 在`ondragstart`事件处理程序中,需要设置数据(即要的行的数据)以及效果。例如: ```html <tr draggable="true" ondragstart="dragStartHandler(event)"> <td>Item 1</td> <td>Item 2</td> <td>Item 3</td> </tr> <script> function dragStartHandler(event) { // 设置数据 event.dataTransfer.setData("text/plain", event.target.innerHTML); // 设置效果 event.dataTransfer.effectAllowed = "move"; } </script> ``` 在`ondragover`事件处理程序中,需要阻止默认行为并设置效果。例如: ```html <tr draggable="true" ondragstart="dragStartHandler(event)" ondragover="dragOverHandler(event)"> <td>Item 1</td> <td>Item 2</td> <td>Item 3</td> </tr> <script> function dragOverHandler(event) { // 阻止默认行为 event.preventDefault(); // 设置效果 event.dataTransfer.dropEffect = "move"; } </script> ``` 最后,在`ondrop`事件处理程序中,需要获取数据并重新排列表格行。例如: ```html <tr draggable="true" ondragstart="dragStartHandler(event)" ondragover="dragOverHandler(event)" ondrop="dropHandler(event)"> <td>Item 1</td> <td>Item 2</td> <td>Item 3</td> </tr> <script> function dropHandler(event) { // 阻止默认行为 event.preventDefault(); // 获取数据 const data = event.dataTransfer.getData("text/plain"); // 重新排列表格行 event.target.innerHTML = data; } </script> ``` 以上代码仅为示例,具体实现还需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值