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 Storeanimation: 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()` methodghostClass: "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,outputevt.dragged; // 被拖动元素evt.draggedRect; // DOMRect {left, top, right, bottom}evt.related; // HTMLElement on which have guidedevt.relatedRect; // DOMRectevt.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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【JavaEE】【多线程】单例模式

目录 一、设计模式1.1 单例模式1.1.1 饿汉模式1.1.2 懒汉模式 1.2 线程安全问题1.3 懒汉模式线程安全问题的解决方法1.3.1 原子性问题解决1.3.2 解决效率问题1.3.3 解决内存可见性问题和指令重排序问题 一、设计模式 在讲解案例前&#xff0c;先介绍一个概念设计模式&#xff…

stm32入门教程--ADC模拟-数字转换器

ADC&#xff08;Analog-Digital Converter&#xff09;模拟-数字转换器 ADC可以将引脚上连续变化的模拟电压转你换位内存中存储的数字变量&#xff0c;建立模拟电路到数字电路的桥梁。 12位逐次逼近型ADC&#xff0c;1us转换时间 输入电压范围&#xff1a;0-3.3V转换结果范围…

Pyramidal Flow使用指南:快手、北大、北邮,开源可免费商用视频生成模型,快速上手教程

什么是 Pyramidal Flow&#xff1f; Pyramidal Flow 是由快手科技、北京大学和北京邮电大学联合推出的开源视频生成模型&#xff0c;它是完全开源的&#xff0c;发布在 MIT 许可证下&#xff0c;允许商业使用、修改和再分发。该模型能够通过文本描述生成最高10秒、分辨率为128…

Embedding 模型和Model 批量推理和多卡部署

批量推理 多卡部署 使用huggingface 【AI大模型】Transformers大模型库&#xff08;七&#xff09;&#xff1a;单机多卡推理之device_map_transformers多卡推理-CSDN博客 首先用 CUDA_VISIBLE_DEVICES1,2,3 python 或者os.environ["CUDA_VISIBLE_DEVICES"] &q…

风力发电场的“守护神”

摘要&#xff1a;作为清洁能源之一&#xff0c;风力发电场近几年装机容量快速增长。8月17日&#xff0c;国家能源局发布1-7月份全国电力工业统计数据。截至7月底&#xff0c;全国累计发电装机容量约27.4亿千瓦&#xff0c;同比增长11.5%。其中&#xff0c;太阳能发电装机容量约…

TCP simultaneous open测试

源代码 /*************************************************************************> File Name: common.h> Author: hsz> Brief:> Created Time: 2024年10月23日 星期三 09时47分51秒**********************************************************************…

转录组上游分析流程(三)

环境部署——数据下载——查看数据(非质控)——数据质控——数据过滤(过滤低质量数据) 测序得到的原始序列含有接头序列和低质量序列&#xff0c;为了保证信息分析的准确性&#xff0c;需要对原始数据进行质量控制&#xff0c;得到高质量序列(Clean Reads)&#xff0c;原始序列…

Linux系统块存储子系统分析记录

1 Linux存储栈 通过网址Linux Storage Stack Diagram - Thomas-Krenn-Wiki-en&#xff0c;可以获取多个linux内核版本下的存储栈概略图&#xff0c;下面是kernel-4.0的存储栈概略图&#xff1a; 2 存储接口、传输速度 和 协议 2.1 硬盘 《深入浅出SSD&#xff1a;固态存储核心…

(二十三)Java反射

1.反射概念 反射允许对成员变量&#xff0c;成员方法和构造方法的信息进行编程访问&#xff0c;通俗理解就是允许从类里面拿东西&#xff0c;用途有提示词等&#xff0c;如下所示都是通过反射实现的 所以&#xff0c;学习反射就是学习从字节码class文件中获取成员信息并且对其…

stable diffusion WEBUI Brief summary

1&#xff0c;rembg(去除背景-》蒙版) import rembg from PIL import Image, ImageOps import numpy as np# 打开图像 input_path "./p_6258838.jpg" input_image Image.open(input_path)# 移除背景&#xff0c;得到带有透明背景的图像 output_image rembg.remove…

利用大模型进行复杂决策制定:PlanRAG技术的研究

人工智能咨询培训老师叶梓 转载标明出处 有效的决策制定对于组织的成功至关重要。传统的决策支持系统虽然在数据分析和决策辅助方面取得了一定的进展&#xff0c;但在处理需要复杂数据分析的决策问题时仍显不足。为了解决这一问题&#xff0c;来自韩国高等科学技术院&#xff…

fpga系列 HDL: 竞争和冒险 01

卡诺图是一种逻辑化简工具&#xff0c;用来在布尔函数的最小项和形式中&#xff0c;找到冗余项并实现逻辑化简。也可用于HDL中竞争和冒险的判断。 最小项 任何一个逻辑函数都能化简为最小项的和的形式对于 n 个变量的布尔表达式&#xff0c;每个变量都必须以原变量&#xff0…

Zabbix企业级分布式监控环境部署

“运筹帷幄之中&#xff0c;决胜千里之外”。在IT运维中&#xff0c;监控占据着重要的地位&#xff0c;按比例来算&#xff0c;说占30%一点也不为过。对IT运维工程师来说&#xff0c;构建一个真正可用的监控告警系统是一项艰巨的任务。在监控系统的开源软件中&#xff0c;可供选…

基于模型划分的云边协同推理算法

摘要 在网络状态和任务需求的动态变化下&#xff0c;为减少模型推理时延和计算成本&#xff0c;在软件定义网络( Software Defined Network&#xff0c;SDN) 中提出了一种基于模型划分的云边协同推理算法。通过构建复杂度预测器分配任务执行环境&#xff0c;采用深度Q网络(Dee…

国产标准数字隔离器的未来---克里雅半导体

标准数字隔离器是电信号隔离技术的重要组成部分&#xff0c;近年来取得了重大进展。随着工业自动化、汽车电子和电信等行业对更高性能的需求不断增长&#xff0c;国内数字隔离器制造商正在稳步赶上全球标准。本文讨论了数字隔离器技术的新兴趋势、材料创新的影响&#xff0c;以…

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

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

一家医药企业终止,收入依赖阿里健康,学术推广费快赶上净利润

知原药业终止原因如下&#xff1a;知原药业报告期三年的推广费用超3亿元&#xff0c;快赶上这三年累计3.68亿元的净利润了&#xff0c;交易所质疑其学术推广费单价合理性、是否存在销售返利。并且&#xff0c;公司研发费用率低于行业平均水平&#xff0c;在电商平台营销主要依赖…

pytorh学习笔记——cifar10(三)模仿VGGNet创建卷积网络

VGG16是由牛津大学视觉几何组&#xff08;Visual Geometry Group&#xff09;提出的一种深度卷积神经网络模型。 VGGNet 探索了卷积神经网络的深度与其性能之间的关系&#xff0c;成功地构筑了 16~19 层深的卷积神经网络&#xff0c;同时拓展性又很强&#xff0c;迁移到其它图片…

【LeetCode】11.盛最多水的容器

思路&#xff1a; 利用双指针法进行移动&#xff0c;一个在头一个在尾&#xff0c;此时宽度最宽&#xff0c;当宽度缩小时&#xff0c;高度发生变化&#xff0c;从而可以找到最大值。 代码&#xff1a; int maxArea(int* height, int heightSize) {int* left height;int* …

仿真学习 | Fluent版本迭代一览及选择指南

在计算机辅助工程&#xff08;CAE&#xff09;领域&#xff0c;软件版本的更新迭代&#xff0c;影响了工程师的工作效率、工作习惯和仿真精度&#xff0c;“如何选择软件版本”也永远是摆在每个初学者面前的第一个难题。 计算流体动力学&#xff08;CFD&#xff09;领域的领军…