JS拖拽排序插件Sortable.js用法实例分析


Posted in Javascript onFebruary 20, 2019

本文实例讲述了JS拖拽排序插件Sortable.js用法。分享给大家供大家参考,具体如下:

最近由于项目功能设计的原因,需要对table中的行实现拖拽排序功能,找来找去发现Sortable.js能很好的满足这个需求,而且它还是开源的,于是乎就开始学习使用Sortable.js,再然后就有了这篇文章。

特点:

  • 轻量级但功能强大
  • 移动列表项时有动画
  • 支持触屏设备和大多数浏览器(IE9及以下除外)
  • 支持单个列表容器内部拖拽排序,也支持两个列表容器互相拖拽排序
  • 支持拖放操作和可选择的文本
  • 非常友善的滚动效果
  • 基于原生HTML5中的拖放API
  • 支持多种框架(Angular、Vue、React等)
  • 支持所有的CSS框架,如:Bootstrap
  • 简单的API,方便调用
  • CDN
  • 不依赖于jQuery

下载地址:https://github.com/RubaXa/Sortable
或者点击此处本站下载

运行效果如下图所示:

JS拖拽排序插件Sortable.js用法实例分析

单个列表容器内部拖拽排序

<head>
 <script src="~/Scripts/jquery-3.3.1.min.js"></script>
 <script src="~/Scripts/Sortable-master/Sortable.min.js"></script>
 <script type="text/javascript">
  $(document).ready(function () {
   var ul = document.getElementById("infos");
   var sortable = new Sortable(ul, {
    handle: "input,li",//设置li、input支持拖拽
    animation: 150,//设置动画时长
    // Element dragging started
    onStart: function (/**Event*/evt) {
     evt.oldIndex; // element index within parent,此处指的是li的索引值
    },
    // Element dragging ended
    onEnd: function (/**Event*/evt) {
     var lis = $("#infos li");
     //拖拽完毕后重新设置序号,使其连续
     for (var i = 0; i < lis.length; i++) {
      var no = $(lis[i]).find("input:eq(0)");
      no.val(i + 1);
     }
    }
   });
  });
 </script>
 <style>
  li{
   cursor:pointer;
   padding-bottom:5px;
   list-style:none;
  }
 </style>
</head>
<body>
 <ul id="infos">
  <li>
   <input type="text" value="1" />
   <input type="text" value="hierarchy" />
   <select>
    <option value="">--请选择--</option>
    <option value="1">objective</option>
    <option value="2">proposition</option>
   </select>
  </li>
  <li>
   <input type="text" value="2" />
   <input type="text" value="hierarchy" />
   <select>
    <option value="">--请选择--</option>
    <option value="1">eliminate</option>
    <option value="2">alige</option>
   </select>
  </li>
  <li>
   <input type="text" value="3" />
   <input type="text" value="hierarchy" />
   <select>
    <option value="">--请选择--</option>
    <option value="1">optimize</option>
    <option value="2">deploy</option>
   </select>
  </li>
 </ul>
</body>

两个列表容器相互拖拽排序

<head>
 <script src="~/Scripts/jquery-3.3.1.min.js"></script>
 <script src="~/Scripts/Sortable-master/Sortable.min.js"></script>
 <script type="text/javascript">
  $(document).ready(function () {
   var infosOne = document.getElementById("infosOne");
   var sortableOne = new Sortable(infosOne, {
    group: "guo",//若需要在两个列表容器间拖拽排序,那group的值必须相同
    handle: "input,li",//设置li、input支持拖拽
    animation: 150,//设置动画时长
    // Element dragging started
    onStart: function (/**Event*/evt) {
     evt.oldIndex; // element index within parent,此处指的是li的索引值
    },
    // Element dragging ended
    onEnd: function (/**Event*/evt) {
     var lis = $("#infosOne li");
     for (var i = 0; i < lis.length; i++) {
      var no = $(lis[i]).find("input:eq(0)");
      no.val(i + 1);
     }
     lis = $("#infosTwo li");
     for (var i = 0; i < lis.length; i++) {
      var no = $(lis[i]).find("input:eq(0)");
      no.val(i + 1);
     }
    }
   });
   var infosTwo = document.getElementById("infosTwo");
   var sortableTwo = new Sortable(infosTwo, {
    group:"guo",//若需要在两个列表容器间拖拽排序,那group的值必须相同
    handle: "input,li",//设置li、input支持拖拽
    animation: 150,//设置动画时长
    // Element dragging started
    onStart: function (/**Event*/evt) {
     evt.oldIndex; // element index within parent,此处指的是li的索引值
    },
    // Element dragging ended
    onEnd: function (/**Event*/evt) {
     var lis = $("#infosOne li");
     for (var i = 0; i < lis.length; i++) {
      var no = $(lis[i]).find("input:eq(0)");
      no.val(i + 1);
     }
     lis = $("#infosTwo li");
     for (var i = 0; i < lis.length; i++) {
      var no = $(lis[i]).find("input:eq(0)");
      no.val(i + 1);
     }
    }
   });
  });
 </script>
</head>
<body>
 <ul id="infosOne">
  <li>
   <input type="text" value="1" />
   <input type="text" value="hierarchy" />
   <select>
    <option value="">--请选择--</option>
    <option value="1">objective</option>
    <option value="2">proposition</option>
   </select>
  </li>
  <li>
   <input type="text" value="2" />
   <input type="text" value="hierarchy" />
   <select>
    <option value="">--请选择--</option>
    <option value="1">eliminate</option>
    <option value="2">alige</option>
   </select>
  </li>
  <li>
   <input type="text" value="3" />
   <input type="text" value="hierarchy" />
   <select>
    <option value="">--请选择--</option>
    <option value="1">optimize</option>
    <option value="2">deploy</option>
   </select>
  </li>
 </ul>
 <hr />
 <ul id="infosTwo">
  <li>
   <input type="text" value="1" />
   <input type="text" value="hierarchy" />
   <select>
    <option value="">--请选择--</option>
    <option value="1">目标任务</option>
    <option value="2">论题议题</option>
   </select>
  </li>
  <li>
   <input type="text" value="2" />
   <input type="text" value="hierarchy" />
   <select>
    <option value="">--请选择--</option>
    <option value="1">消除排除</option>
    <option value="2">机敏的敏捷的</option>
   </select>
  </li>
  <li>
   <input type="text" value="3" />
   <input type="text" value="hierarchy" />
   <select>
    <option value="">--请选择--</option>
    <option value="1">优化使最优化</option>
    <option value="2">发布部署</option>
   </select>
  </li>
 </ul>
</body>

常见配置项及事件

var sortable = new Sortable(el, {
 group: "name", // or { name: "...", pull: [true, false, clone], put: [true, false, array] }
 sort: true, // sorting inside list
 delay: 0, // time in milliseconds to define when the sorting should start
 touchStartThreshold: 0, // px, how many pixels the point should move before cancelling a delayed drag event
 disabled: false, // Disables the sortable if set to true.
 store: null, // @see Store
 animation: 150, // ms, animation speed moving items when sorting, `0` — without animation
 handle: ".my-handle", // Drag handle selector within list items
 filter: ".ignore-elements", // Selectors that do not lead to dragging (String or Function)
 preventOnFilter: true, // Call `event.preventDefault()` when triggered `filter`
 draggable: ".item", // Specifies which items inside the element should be draggable
 ghostClass: "sortable-ghost", // Class name for the drop placeholder
 chosenClass: "sortable-chosen", // Class name for the chosen item
 dragClass: "sortable-drag", // Class name for the dragging item
 dataIdAttr: 'data-id',
 forceFallback: false, // ignore the HTML5 DnD behaviour and force the fallback to kick in
 fallbackClass: "sortable-fallback", // Class name for the cloned DOM Element when using forceFallback
 fallbackOnBody: false, // Appends the cloned DOM Element into the Document's Body
 fallbackTolerance: 0, // Specify in pixels how far the mouse should move before it's considered as a drag.
 scroll: true, // or HTMLElement
 scrollFn: function(offsetX, offsetY, originalEvent, touchEvt, hoverTargetEl) { ... }, // if you have custom scrollbar scrollFn may be used for autoscrolling
 scrollSensitivity: 30, // px, how near the mouse must be to an edge to start scrolling.
 scrollSpeed: 10, // px
 setData: function (/** DataTransfer */dataTransfer, /** HTMLElement*/dragEl) {
  dataTransfer.setData('Text', dragEl.textContent); // `dataTransfer` object of HTML5 DragEvent
 },
 // Element is chosen
 onChoose: function (/**Event*/evt) {
  evt.oldIndex; // element index within parent
 },
 // Element dragging started
 onStart: function (/**Event*/evt) {
  evt.oldIndex; // element index within parent
 },
 // Element dragging ended
 onEnd: function (/**Event*/evt) {
  var itemEl = evt.item; // dragged HTMLElement
  evt.to; // target list
  evt.from; // previous list
  evt.oldIndex; // element's old index within old parent
  evt.newIndex; // element's new index within new parent
 },
 // Element is dropped into the list from another list
 onAdd: function (/**Event*/evt) {
  // same properties as onEnd
 },
 // Changed sorting within list
 onUpdate: function (/**Event*/evt) {
  // same properties as onEnd
 },
 // Called by any change to the list (add / update / remove)
 onSort: function (/**Event*/evt) {
  // same properties as onEnd
 },
 // Element is removed from the list into another list
 onRemove: function (/**Event*/evt) {
  // same properties as onEnd
 },
 // Attempt to drag a filtered element
 onFilter: function (/**Event*/evt) {
  var itemEl = evt.item; // HTMLElement receiving the `mousedown|tapstart` event.
 },
 // Event when you move an item in the list or between lists
 onMove: function (/**Event*/evt, /**Event*/originalEvent) {
  // Example: http://jsbin.com/tuyafe/1/edit?js,output
  evt.dragged; // dragged HTMLElement
  evt.draggedRect; // TextRectangle {left, top, right и bottom}
  evt.related; // HTMLElement on which have guided
  evt.relatedRect; // TextRectangle
  originalEvent.clientY; // mouse position
  // return false; — for cancel
 },
 // Called when creating a clone of element
 onClone: function (/**Event*/evt) {
  var origEl = evt.item;
  var cloneEl = evt.clone;
 }
});

属性

group:string or array
sort:boolean 定义是否列表单元是否可以在列表容器内进行拖拽排序;
delay:number 定义鼠标选中列表单元可以开始拖动的延迟时间;
disabled:boolean 定义是否此sortable对象是否可用,为true时sortable对象不能拖放排序等功能,为false时为可以进行排序,相当于一个开关;
animation:number 单位:ms,定义排序动画的时间;
handle:selector 格式为简单css选择器的字符串,使列表单元中符合选择器的元素成为拖动的手柄,只有按住拖动手柄才能使列表单元进行拖动;
filter:selector 格式为简单css选择器的字符串,定义哪些列表单元不能进行拖放,可设置为多个选择器,中间用“,”分隔;
draggable:selector 格式为简单css选择器的字符串,定义哪些列表单元可以进行拖放
ghostClass:selector 格式为简单css选择器的字符串,当拖动列表单元时会生成一个副本作为影子单元来模拟被拖动单元排序的情况,此配置项就是来给这个影子单元添加一个class,我们可以通过这种方式来给影子元素进行编辑样式;
chosenClass:selector 格式为简单css选择器的字符串,当选中列表单元时会给该单元增加一个class;
forceFallback:boolean 如果设置为true时,将不使用原生的html5的拖放,可以修改一些拖放中元素的样式等;
fallbackClass:string 当forceFallback设置为true时,拖放过程中鼠标附着单元的样式;
scroll:boolean 默认为true,当排序的容器是个可滚动的区域,拖放可以引起区域滚动

事件:

onChoose:function 列表单元被选中的回调函数
onStart:function 列表单元拖动开始的回调函数
onEnd:function 列表单元拖放结束后的回调函数
onAdd:function 列表单元添加到本列表容器的回调函数
onUpdate:function 列表单元在列表容器中的排序发生变化后的回调函数
onRemove:function 列表元素移到另一个列表容器的回调函数
onFilter:function 试图选中一个被filter过滤的列表单元的回调函数
onMove:function 当移动列表单元在一个列表容器中或者多个列表容器中的回调函数
onClone:function 当创建一个列表单元副本的时候的回调函数

事件对象:

事件对象在各个函数中略有不同,可通过输出对象查看对象的属性,下面简单列举几个:

to:HTMLElement--移动到列表容器
from:HTMLElement--来源的列表容器
item:HTMLElement--被移动的列表单元
clone:HTMLElement--副本的列表单元
oldIndex:number/undefined--在列表容器中的原序号
newIndex:number/undefined--在列表容器中的新序号

方法

option(name[,value])
获得或者设置项参数,使用方法类似于jQuery用法,没有第二个参数为获得option中第一个参数所对应的值,有第二个参数时,将重新赋给第一个参数所对应的值;

closest
返回满足selector条件的元素集合中的第一个项

toArray()
序列化可排序的列表单元的data-id(可通过配置项中dataIdAttr修改)放入一个数组,并返回这个数组中

sort()
通过自定义列表单元的data-id的数组对列表单元进行排序

save()

destroy()

Javascript 相关文章推荐
JS 容错处理代码, 屏蔽错误信息
Mar 09 Javascript
javascript 操作Word和Excel的实现代码
Oct 26 Javascript
点击弹出层外区域关闭弹出层jquery特效示例
Aug 25 Javascript
原生js和jquery中有关透明度设置的相关问题
Jan 08 Javascript
使用jQuery异步加载 JavaScript脚本解决方案
Apr 20 Javascript
jquery实现个人中心导航菜单效果和美观都非常不错
Sep 02 Javascript
分享一款基于jQuery的视频播放插件
Oct 09 Javascript
node.js中的fs.symlink方法使用说明
Dec 15 Javascript
JQuery中extend的用法实例分析
Feb 08 Javascript
Vue 实现前端权限控制的示例代码
Jul 09 Javascript
详解如何使用React Hooks请求数据并渲染
Oct 18 Javascript
如何在Express4.x中愉快地使用async的方法
Nov 18 Javascript
详解webpack 最简打包结果分析
Feb 20 #Javascript
jQuery表单元素过滤选择器用法实例分析
Feb 20 #jQuery
jQuery内容过滤选择器与子元素过滤选择器用法实例分析
Feb 20 #jQuery
小程序红包雨的实现示例
Feb 19 #Javascript
vue动态添加路由addRoutes之不能将动态路由存入缓存的解决
Feb 19 #Javascript
jQuery选择器之基本过滤选择器用法实例分析
Feb 19 #jQuery
Vue 实现手动刷新组件的方法
Feb 19 #Javascript
You might like
PHP中ini_set与ini_get用法实例
2014/11/04 PHP
怎样搭建PHP开发环境
2015/07/28 PHP
PHP基于redis计数器类定义与用法示例
2018/02/08 PHP
PHP中in_array的隐式转换的解决方法
2018/03/06 PHP
php查询内存信息操作示例
2019/05/09 PHP
麻雀虽小五脏俱全 Dojo自定义控件应用
2010/09/04 Javascript
Jquery判断IE6等浏览器的代码
2011/04/05 Javascript
button没写type=button会导致点击时提交
2014/03/06 Javascript
jQuery实现定时读取分析xml文件的方法
2015/07/16 Javascript
JavaScript实现简单Tip提示框效果
2016/04/20 Javascript
jQuery 3.0中存在问题及解决办法
2016/07/15 Javascript
javaScript动态添加Li元素的实例
2018/02/24 Javascript
vue-baidu-map 进入页面自动定位的解决方案(推荐)
2018/04/28 Javascript
JavaScript高阶教程之“==”隐藏下的类型转换
2019/04/11 Javascript
Vue keepAlive 数据缓存工具实现返回上一个页面浏览的位置
2019/05/10 Javascript
vue-next/runtime-core 源码阅读指南详解
2019/10/25 Javascript
Layer UI表格列日期格式化及取消自动填充日期的实现方法
2020/05/10 Javascript
VueJS实现用户管理系统
2020/05/29 Javascript
vue实现移动端触屏拖拽功能
2020/08/21 Javascript
Javascript 模拟mvc实现点餐程序案例详解
2020/12/24 Javascript
[51:29]Alliance vs TNC 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/18 DOTA
Python中下划线的使用方法
2015/03/27 Python
pandas 按照特定顺序输出的实现代码
2018/07/10 Python
在python中使用with打开多个文件的方法
2019/01/07 Python
Python数据可视化库seaborn的使用总结
2019/01/15 Python
python实现DEM数据的阴影生成的方法
2019/07/23 Python
django执行原始查询sql,并返回Dict字典例子
2020/04/01 Python
python torch.utils.data.DataLoader使用方法
2020/04/02 Python
python的flask框架难学吗
2020/07/31 Python
python编写实现抽奖器
2020/09/10 Python
描述一下JVM加载class文件的原理机制
2013/12/08 面试题
2014年五一活动策划方案
2014/03/15 职场文书
四年级小学生评语
2014/12/26 职场文书
违纪开除通知书
2015/04/25 职场文书
python如何进行基准测试
2021/04/26 Python
ztree+ajax实现文件树下载功能
2021/05/18 Javascript