sortablejs(前端拖拽排序的实现)

源文档:sortablejs - npm

安装

npm install sortablejs --save

引入项目

import Sortable from 'sortablejs';

使用示例

<template>
    <ul id="items">
	   <li>item 1</li>
	   <li>item 2</li>
	   <li>item 3</li>
    </ul>
</template>

<script setup>
import Sortable from 'sortablejs';

const el = document.getElementById('items');
const sortable = Sortable.create(el);

</script>


<style scoped lang="scss">

</style>

sortablejs的配置项

const sortable = new Sortable(el, {
	group: "name",  // or { name: "...", pull: [true, false, 'clone', array], put: [true, false, array] }
	sort: true,  //是否可以在列表内排序,默认开启
	delay: 0, //拖拽延迟时间(通常用于移动端实现长按拖拽)
	delayOnTouchOnly: false, //只有当用户使用触摸时才会延迟
	touchStartThreshold: 0, // 在取消延迟拖动事件之前,应该移动多少像素(px)
	disabled: false, //如果设置为true,则禁用可排序。
	store: null,  // @see Store
	animation: 150,  // ms,排序时移动项目的动画速度,设置0则无过渡动画
	easing: "cubic-bezier(1, 0, 0, 1)", //渐变动画,默认为null,可访问https://easings.net/查看示例
	handle: ".my-handle",  // 需要绑定的元素(比如我们想长按某个盒子来拖拽其父元素,那么此时我们仅需要给这个盒子添加这里配置的类型即可)
	filter: ".ignore-elements",  //不需要进行拖动的元素(给元素添加这个选项配置的类名后,该元素将不会被拖动)
	preventOnFilter: true, // 当触发filter时调用event.preventDefault()
	draggable: ".item",  // 指定元素内的哪些项可以被拖动
	dataIdAttr: 'data-id', // HTML attribute that is used by the `toArray()` method
	ghostClass: "sortable-ghost",  //占位元素类名,可以对此类名进行配置以实现特定效果(拖拽时,sortablejs会生成一个占位元素占据元素的位置,此类名主要用于控制这个元素的样式)
	chosenClass: "sortable-chosen",  //所选项目的类名
	dragClass: "sortable-drag",  //拖动项的类名
	swapThreshold: 1, //交换区阈值
	invertSwap: false, //如果设置为true,将始终使用反向交换区
	invertedSwapThreshold: 1, //反转交换区的阈值(默认设置为swapThreshold值)
	direction: 'horizontal', // 可分拣方向(如果没有给出,将自动检测)
	forceFallback: false,  //忽略HTML5 行为并强制回退
	fallbackClass: "sortable-fallback",  //使用forceFallback时克隆的DOM元素的类名
	fallbackOnBody: false,  //将克隆的DOM元素附加到文档正文中
	fallbackTolerance: 0, //以像素为单位指定鼠标在被视为拖动之前应该移动多远。
	dragoverBubble: false,//拖拽经过时是否冒泡
	removeCloneOnHide: true, //当clone元素未显示时将其删除,而不是将其隐藏
	emptyInsertThreshold: 5, //px,鼠标距离必须为空可排序,才能将拖动元素插入其中


	setData: function (/** DataTransfer */dataTransfer, /** HTMLElement*/dragEl) {
		dataTransfer.setData('Text', dragEl.textContent); //HTML5 DragEvent的DataTransfer对象
	},

	//元素被选中时触发
	onChoose: function (/**Event*/evt) {
		evt.oldIndex;  //当前元素在父元素中的索引
	},

	//元素未被选中时(与onEnd事件相似)
	onUnchoose: function(/**Event*/evt) {
		// same properties as onEnd
	},

	//开始拖拽时
	onStart: function (/**Event*/evt) {
		evt.oldIndex;  //当前元素在父元素中的索引
	},

	//拖拽完成时
	onEnd: function (/**Event*/evt) {
		var itemEl = evt.item;  //被拖拽的元素
		evt.to;    //目标列表
		evt.from;  //初始列表
		evt.oldIndex;  //初始列表的初始索引(即拖拽改变之前的列表索引)
		evt.newIndex;  //元素在新父级中的新索引(即拖拽之后形成的列表的索引)
		evt.oldDraggableIndex; //元素在旧父元素内的旧索引,仅计算可拖动元素		 
        evt.newDraggableIndex; //元素在新父级中的新索引,仅计算可拖动元素
		evt.clone //克隆元素		
        evt.pullMode;  //当项目位于另一个可排序的位置时:如果是克隆,则为“clone”;如果是移 
        动,则为true

	//元素从另一个列表中删除到列表中
	onAdd: function (/**Event*/evt) {
		//与onEnd具有相同的属性
	},

	//更改列表中的排序
	onUpdate: function (/**Event*/evt) {
		//与onEnd具有相同的属性
	},

	//由列表的任何更改调用(添加/更新/删除)
	onSort: function (/**Event*/evt) {
		//与onEnd具有相同的属性
	},

	//元素从列表中删除到另一个列表中
	onRemove: function (/**Event*/evt) {
		//与onEnd具有相同的属性
	},

	//尝试拖动已过滤的元素
	onFilter: function (/**Event*/evt) {
		var itemEl = evt.item;  //HTMLElement接收到“mousedown”、“tapstart”事件。
	},

	//在列表中或列表之间移动项目的事件
	onMove: function (/**Event*/evt, /**Event*/originalEvent) {
		// Example: https://jsbin.com/nawahef/edit?js,output
		evt.dragged; // 被拖动元素
		evt.draggedRect; // DOMRect {left, top, right, bottom}
		evt.related; // HTMLElement on which have guided
		evt.relatedRect; // DOMRect
		evt.willInsertAfter; //布尔值,默认为真。为真的情况下Sortable将在目标后插入拖动元素
		originalEvent.clientY; //鼠标位置
		// return false; — for cancel
		// return -1; — 在目标之前插入
		// return 1; — 在目标之后插入
		// return true; —根据方向保留默认插入点
		// return void; —根据方向保留默认插入点
	},

	//创建元素克隆时调用
	onClone: function (/**Event*/evt) {
		var origEl = evt.item;
		var cloneEl = evt.clone;
	},

	//当拖动元素改变位置时调用
	onChange: function(/**Event*/evt) {
		evt.newIndex //使用此事件的最可能原因是获取拖动元素的当前索引
		// same properties as onEnd
	}
});

vue3中的使用演示

<template>
  <div class="home">
     <ul ref="boxRef" >
         <li v-for="item in list"  :key="item.id" >
            <div class="bread">
                <van-icon name="wap-nav" size="30px"  ></van-icon>
            </div>  
            <span> {{ item.text }}</span>
         </li>
     </ul>
  </div>
</template>

<script setup>
import { ref,onMounted } from 'vue';
import Sortable from 'sortablejs';

//sortable实例
const instance = ref(null)

const list = ref([
  {
    text: '张三',
    id: 1,
  },
  {
    text: '李四',
    id: 2,
  },
  {
    text: '王五',
    id: 3,
  },
  {
    text: '赵四',
    id: 4,
  },
  {
    text: '王大麻子',
    id: 5,
  },
]);

//获取容器dom元素
const boxRef = ref(null)

onMounted(()=>{
  instance.value = Sortable.create(boxRef.value,{
         handle:'.bread', //设置了此类名,只有长按有这个类名的元素才能拖动(注意这里要带上选择器符号)
         delay:600, //延迟600毫秒才能拖动
         chosenClass:"move" //可以拖动时,被拖动项的类名
  }) 
})
</script>

<style scoped lang="less">
.move{
  background: orange;
}
.box {
  margin: 20px auto;
  width: 600px;
  height: 600px;
  box-shadow: 0 0 3px 5px #ccc;
}
ul{
  margin:10px auto;
  width:600px;
  li{
    margin:10px 0;
    display: flex;
    align-items: center;
    height:80px;
    line-height: 80px;
    text-align: center;
    background:#ccc; 
    .bread{
      margin: 0 20px;
      display: flex;
      align-items: center;
      width:50px;
      height:50px;
    }
  }
}
</style>

在实际的使用中我们通常使用sortablejs做拖拽排序,这就会涉及到异步请求及请求发送失败的情况。那么就会发现一个问题,当我们的请求发送失败后按照常理应该还原排序但是sortablejs似乎并没有给予相应的方法来实现这个功能。我们可以如下操作:

<template>
  <div class="home">
    <ul ref="boxRef" @sort="onSort">
      <li v-for="item in list" :key="item.id">
        <div class="bread">
          <van-icon name="wap-nav" size="30px"></van-icon>
        </div>
        <span> {{ item.text }}</span>
      </li>
    </ul>
  </div>
</template>

<script setup >
import { ref, onMounted } from 'vue';
import Sortable from 'sortablejs';

//获取容器dom元素
const boxRef = ref(null);

const list = ref([
  {
    text: '张三',
    id: 1,
  },
  {
    text: '李四',
    id: 2,
  },
  {
    text: '王五',
    id: 3,
  },
  {
    text: '赵四',
    id: 4,
  },
  {
    text: '王大麻子',
    id: 5,
  },
]);


//sortable实例
const instance = ref(null);


//排序时触发的回调函数
const onSort = async (value) => {
  const { oldIndex, newIndex, from } = value;
  try {
    //模拟的异步请求失败情况
    await new Promise((resolve, reject) => {
      reject(new Error('发送错误'));
    });
  } catch (error) {
    //请求失败时还原排序
    const List = Array.from(from.children);
    const item = List.splice(newIndex, 1)[0];
    if (oldIndex > newIndex) {
      from.insertBefore(item, List[oldIndex + 1]);
    } else {
      from.insertBefore(item, List[oldIndex]);
    }
  }
};


onMounted(() => {
  //初始化sortablejs实例
  instance.value = Sortable.create(boxRef.value, {
    handle: '.bread', //设置了此类名,只有长按有这个类名的元素才能拖动(注意这里要带上选择器符号)
    //  delay:600, //延迟600毫秒才能拖动
    chosenClass: 'move', //可以拖动时,被拖动项的类名(可以自定义样式)
  });
});
</script>

<style scoped lang="less">
.move {
  background: orange;
}
.box {
  margin: 20px auto;
  width: 600px;
  height: 600px;
  box-shadow: 0 0 3px 5px #ccc;
}
ul {
  margin: 10px auto;
  width: 600px;
  li {
    margin: 10px 0;
    display: flex;
    align-items: center;
    height: 80px;
    line-height: 80px;
    text-align: center;
    background: #ccc;
    .bread {
      margin: 0 20px;
      display: flex;
      align-items: center;
      width: 50px;
      height: 50px;
    }
  }
}
</style>

这样就可以实现日常的工作需求,考虑到每次写这么多东西会很麻烦,我们可以使用vue的自定义指令将它封装成一个指令。目前已经有插件完成了这一步骤,大家也可以尝试一下这个插件。

传送门:vue3-sortablejs - npm

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/900729.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《Python游戏编程入门》注-第2章2

《Python游戏编程入门》的“2.2.5 绘制线条”中提到了通过pygame库绘制线条的方法。 1 相关函数介绍 通过pygame.draw模块中的line()函数来绘制线条&#xff0c;该函数的格式如下所示。 line(surface, color, start_pos, end_pos, width1) -> Rect 其中&#xff0c;第一…

开源限流组件分析(二):uber-go/ratelimit

文章目录 本系列漏桶限流算法uber的漏桶算法使用mutex版本数据结构获取令牌松弛量 atomic版本数据结构获取令牌测试漏桶的松弛量 总结 本系列 开源限流组件分析&#xff08;一&#xff09;&#xff1a;juju/ratelimit开源限流组件分析&#xff08;二&#xff09;&#xff1a;u…

部署前后端分离若依项目--CentOS7宝塔版

准备&#xff1a; CentOS7服务器一台 通过网盘分享的文件&#xff1a;CentOS 7 h 链接: https://pan.baidu.com/s/17DF8eRSSDuj9VeqselGa_Q 提取码: s7x4 大家有需要可以下载这个&#xff0c;密码61 若依前端编译后文件 通过网盘分享的文件&#xff1a;ruoyi-admin.jar 链…

生信软件39 - GATK最佳实践流程重构,提高17倍分析速度的LUSH流程

1. LUSH流程简介 基因组测序通常用于分子诊断、分期和预后&#xff0c;而大量测序数据在分析时间方面提出了挑战。 对于从FASTQ到VCF的整个流程&#xff0c;LUSH流程在非GVCF和GVCF模式下都大大降低了运行时间&#xff0c;30 X WGS数据耗时不到2 h&#xff0c;从BAM到VCF约需…

【计网】UDP Echo Server与Client实战:从零开始构建简单通信回显程序

目录 前言&#xff1a; 1.实现udpserver类 1.1.创建udp socket 套接字 --- 必须要做的 socket&#xff08;&#xff09;讲解 代码实现&#xff1a;​编辑 代码讲解&#xff1a; 1.2.填充sockaddr_in结构 代码实现&#xff1a; 代码解析&#xff1a; 1.3.bind sockfd和…

linux中级wed服务器(https搭建加密服务器)

一。非对称加密算法&#xff1a; 公钥&#xff1a;公共密钥&#xff0c;开放 私钥&#xff1a;私有密钥&#xff0c;保密 1.发送方用自己的公钥加密&#xff0c;接受方用发送方的私钥解密&#xff1a;不可行 2.发送方用接受方的公钥加密&#xff0c;接受方用自己的私钥解密…

ffmpeg视频滤镜: 色温- colortemperature

滤镜简述 colortemperature 官网链接 》 FFmpeg Filters Documentation 这个滤镜可以调节图片的色温&#xff0c;色温值越大显得越冷&#xff0c;可以参考一下下图&#xff1a; 咱们装修的时候可能会用到&#xff0c;比如选择灯还有地板的颜色的时候&#xff0c;选暖色调还是…

【论文+源码】基于spring boot的垃圾分类网站

创建一个基于Spring Boot的垃圾分类网站涉及多个步骤&#xff0c;包括环境搭建、项目创建、数据库设计、后端服务开发、前端页面设计等。下面我将引导您完成这个过程。 第一步&#xff1a;准备环境 确保您的开发环境中安装了以下工具&#xff1a; Java JDK 8 或更高版本Mav…

Unity URP ShaderGraph 基本设置

先简单了解一下各种渲染管线之间的区别 Unity 从 2019.3 版本开始正式支持通用渲染管线&#xff08;URP&#xff0c;Universal Render Pipeline&#xff09;。URP 是轻量渲染管线&#xff08;LWRP&#xff0c;Lightweight Render Pipeline&#xff09;的升级和重命名版本&…

【解决】使用Hypermark将Markdown文件转化为HTML文件

写在前面&#xff1a; 如果文章对你有帮助&#xff0c;记得点赞关注加收藏一波&#xff0c;利于以后需要的时候复习&#xff0c;多谢支持&#xff01; 文章目录 一、文件准备&#xff08;一&#xff09;HTML模板文件&#xff08;二&#xff09;MD文件夹和储存文件夹 二、文件转…

COSCon'24 志愿者招募令:共创开源新生活!

亲爱的开源爱好者们&#xff0c; 第九届中国开源年会&#xff08;COSCon24&#xff09;即将在北京中关村国家自主创新示范区会议中心于2024年11月2日至3日隆重举行。今年的主题是“Open Source, Open Life&#xff5c;开源新生活”&#xff0c;旨在探索开源技术如何在各个领域推…

日常记录,使用springboot,vue2,easyexcel使实现字段的匹配导入

目前的需求是数据库字段固定&#xff0c;而excel的字段不固定&#xff0c;需要实现excel导入到一个数据库内。 首先是前端的字段匹配&#xff0c;显示数据库字段和表头字段 读取表头字段&#xff1a; 我这里实现的是监听器导入&#xff0c;需要新建一个listen类。 读Excel …

uniApp 加载google地图 并规划路线

uniApp 加载google地图 并规划路线 备注:核心代码实例 备注: 打开谷歌地图失败的话 参考google开发文档 https://developers.google.com/maps/documentation/urls/ios-urlscheme?hlzh-cn#swift核心代码 mounted() {this.loadGoogleMapsScript(); }, methods: {//加载loadGo…

AI服务器HBA卡的国产PCIe4.0/5.0 switch信号完整性设计与实现,支持定制(二)

表 &#xff12; 展示了 &#xff30;&#xff23;&#xff22; 板所选介质材料 &#xff30;&#xff33;&#xff32;&#xff14;&#xff10;&#xff10;&#xff10;&#xff21;&#xff35;&#xff33;&#xff17;&#xff10;&#xff13; &#xff0c; &#xff3…

解决Redis缓存穿透(缓存空对象、布隆过滤器)

文章目录 背景代码实现前置实体类常量类工具类结果返回类控制层 缓存空对象布隆过滤器结合两种方法 背景 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这样缓存永远不会生效&#xff0c;这些请求都会打到数据库 常见的解决方案有两种&#xff0c;分别…

使用DolphinScheduler接口实现批量导入工作流并上线

使用DS接口实现批量导入工作量并上线脚本 前面实现了批量生成DS的任务&#xff0c;当导入时发现只能逐个导入&#xff0c;因此通过接口实现会更方便。 DS接口文档 DS是有接口文档的地址是 http://IP:12345/dolphinscheduler/swagger-ui/index.html?languagezh_CN&lang…

安全见闻---清风

注&#xff1a;本文章源于泷羽SEC&#xff0c;如有侵权请联系我&#xff0c;违规必删 学习请认准泷羽SEC学习视频:https://space.bilibili.com/350329294 安全见闻1 泷哥语录&#xff1a;安全领域什么都有&#xff0c;不要被表象所迷惑&#xff0c;无论技术也好还是其他方面…

网站建设中需要注意哪些安全问题?----雷池社区版

服务器与应用安全指南 1. 服务器安全 1.1 操作系统安全 及时更新补丁&#xff1a;确保操作系统始终安装最新补丁&#xff0c;以防范系统漏洞。例如&#xff0c;Windows Server 定期推送安全更新&#xff0c;修复如远程代码执行等潜在威胁。优化系统服务配置&#xff1a;关闭不…

PoissonRecon学习笔记

1. Screened Poisson Reconstruction (SPR) 源码&#xff1a;https://github.com/mkazhdan/PoissonRecon However, as noted by several researchers, it suffers from a tendency to over-smooth the data. 泊松重建存在过度平滑的现象。 方法&#xff1a;position and gradi…

【C++】一文带你深入理解C++异常机制

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;C 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 前言一、C语言处理错误的方式二、C异常三、异常的使用3.1 异常的抛出和捕获3.2 异常的重新抛出3.3 异常安全3.4 异常规范 四、自定义异…