dragula/plain-draggable拖拽排序的另一种选择

在Vue3项目中,对于flex不定高度的列表布局,文章比较了dragula和plain-draggable两个拖拽排序库。尽管dragula功能丰富,但其在某些场景下兼容性不如sortablejs。plain-draggable则封装较少,需要手动处理排序和特定样式。文章提供了使用这两个库的代码示例,并特别指出plain-draggable初始化时的注意事项,以及在有抽屉效果的item中可能需要额外计算高度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先把调研结果说在前面,因为列表是flex不定高度的布局,
dragula的兼容性没有sortablejs好,环境是在vue3.0项目中使用的
下面是其他拖拽排序的方案,dragula封装的功能比较多,plain-draggable库封装的功能不多,

先上dragula使用代码
npm install dragula @types/dragula
//"dragula": "^3.7.3",
//"@types/dragula": "^3.7.1",
// package.json
npm install dragula
//"dragula": "^3.7.3",
// package.json

/*上面是安装命令*/
import dragula from 'dragula';
// import type { Draggable } from 'dragula';  这次不用ts
const container = this.$refs.dragulaContainer;
        const drake = dragula([container], {
            containers: [container],
            invalid: function (el) {
                return el.classList.contains('ignore-elements');
              }
        });
    
        drake.on('drop', (el, target, source, sibling) => {
          console.log('Element dropped!',el.index, target, source, sibling);
        });
// 注意监听的方法中传入的是el元素,配合框架使用时需要先将index渲染时放入属性,再拿取监听
// option还支持copy等选项,详见readme.md
再来plain-draggable库

注意两点
1.npm安装需要自行安装依赖cd node_modules/plain-draggable npm i;或者直接在项目中依次npm install 4个依赖
2.demo代码在网站源码中,自行右键查看网页源代码

plain-draggable初始化时绑定的元素并不是含有list的容器,这点要区分,可拖动的类名class自行在元素中直接添加即可
plain-draggable偏向容器内自由拖动,列表拖动排序需要自己写排序功能,
而且业务中的item有抽屉效果,按demo需要重新算高度,

demo网址
github网址

demo讲解

demo结构
class=“ex-230-item draggable cat”*5// 5个此元素组成列表
cat是修改了默认类名’plain-draggable’
PlainDraggable.draggableClass = ‘cat’;

以下是demo代码
var elmItems = Array.prototype.slice.call(document.getElementsByClassName('ex-230-item')),
    rect = elmItems[0].getBoundingClientRect(),
    itemHeight = rect.height,
    itemsTop = elmItems.map(function(v, i) {
      return Math.round(rect.top + window.pageYOffset + itemHeight * i);
    }),
    items = [];

  function sort(targetItem, top) {
    var curIndex = items.indexOf(targetItem),
      newIndex = itemsTop.indexOf(Math.round(top));
    if (newIndex !== -1 && newIndex !== curIndex) {
      items.splice(newIndex, 0, items.splice(curIndex, 1)[0]);
      items.forEach(function(item, i) {
        if (item !== targetItem) { item.top = itemsTop[i]; }
      });
    }
  }

  items = elmItems.map(function(elmItem) {
    return new PlainDraggable(elmItem, {
      snap: {
        y: {step: itemHeight},
        side: 'start'
      },
      onDrag: function(moveTo) {
        if (!moveTo.snapped) { return false; }
        sort(this, moveTo.top);
        return true;
      }
    });
  });
// GPT自动讲解
此代码使用 plain-draggable 库实现垂直列表拖动和排序效果。
首先,代码选择所有类名为 ex-230-item 的元素,并使用 Array.prototype.slice.call() 将生成的 HTMLCollection 转换为数组。 然后它获取数组中第一个元素的边界矩形并计算每个项目的高度。 它还根据其索引和项目高度计算每个项目的顶部位置。
接下来,代码定义了一个 sort() 函数,它将目标项目和顶部位置作为参数。 该函数计算目标项目在项目数组中的当前索引和基于顶部位置的新索引。 如果新索引与当前索引不同,则函数将目标项目移动到项目数组中的新索引并更新数组中每个项目的顶部位置。
最后,代码为 elmItems 数组中的每个项目创建一个 PlainDraggable 实例。 捕捉选项设置为将项目捕捉到 y 轴上每个步骤(即每个项目)的开始。 onDrag 事件用于调用 sort() 函数并在拖动项目时更新项目数组。
总的来说,这段代码是一个很好的例子,展示了如何使用plain-draggable实现垂直列表的拖拽排序效果。
if(this.pageNum>pageNumber){
                setTimeout(()=>{
                    return this.renderPage(pageNumber+1)
                },0)
            }
this.loadNumber = pageNumber
            if(this.loadlimit>pageNumber&&this.pageNum>pageNumber){
                setTimeout(()=>{
                    return this.renderPage(this.loadNumber+1)
                },0)
            }
        nextpage(){
//mounted触发
            const container = document.querySelector('.pdfWrapper')
            container.addEventListener('scroll',()=>{
                // 加1是解决精度问题jg
                const isScrolledToBottom = container.scrollTop + container.clientHeight + 1 >= container.scrollHeight;
                if(isScrolledToBottom){
                    this.loadlimit = this.loadlimit+5
                    this.renderPage(this.loadNumber+1)
                }
            })
        },
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值