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 相关文章推荐
jquery 关于event.target使用的几点说明介绍
Apr 26 Javascript
JS Loading功能的简单实现
Nov 29 Javascript
如何实现textarea里的不同文本显示不同颜色
Jan 20 Javascript
js实现jquery的offset()方法实例
Jan 10 Javascript
cocos2dx骨骼动画Armature源码剖析(三)
Sep 08 Javascript
JavaScript判断页面加载完之后再执行预定函数的技巧
May 17 Javascript
深入分析javascript中console命令
Aug 14 Javascript
利用vue-router实现二级菜单内容转换
Nov 30 Javascript
jQuery输入框密码的显示隐藏【代码分享】
Apr 29 jQuery
Three.js入门之hello world以及如何绘制线
Sep 25 Javascript
JS寄快递地址智能解析的实现代码
Jul 16 Javascript
在vue中created、mounted等方法使用小结
Jul 21 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处理Oracle的CLOB实例
2014/11/03 PHP
php获取从html表单传递数组的方法
2015/03/20 PHP
php使用pclzip类实现文件压缩的方法(附pclzip类下载地址)
2016/04/30 PHP
Joomla实现组件中弹出一个模式(modal)窗口的方法
2016/05/04 PHP
PHP实现普通hash分布式算法简单示例
2018/08/06 PHP
Nodejs异步回调的优雅处理方法
2014/09/25 NodeJs
Bootstrap中点击按钮后变灰并显示加载中实例代码
2016/09/23 Javascript
微信小程序开发实战教程之手势解锁
2016/11/18 Javascript
微信小程序 按钮滑动的实现方法
2017/09/27 Javascript
JavaScript去掉数组重复项的方法分析【测试可用】
2018/07/19 Javascript
jQuery实现获取当前鼠标位置并输出功能示例
2019/01/05 jQuery
javascript移动端 电子书 翻页效果实现代码
2019/09/07 Javascript
[06:25]第二届DOTA2亚洲邀请赛主赛事第二天比赛集锦.mp4
2017/04/03 DOTA
python使用ddt过程中遇到的问题及解决方案【推荐】
2018/10/29 Python
Django单元测试中Fixtures用法详解
2020/02/25 Python
Django-migrate报错问题解决方案
2020/04/21 Python
详解HTML5表单新增属性
2016/12/21 HTML / CSS
钉钉企业内部H5微应用开发详解
2020/05/12 HTML / CSS
美国卡车、吉普车和SUV零件网站:4 Wheel Parts
2016/11/24 全球购物
怎样创建、运行java程序
2014/08/01 面试题
STP的判定过程
2012/10/01 面试题
经济管理专业求职信
2014/06/09 职场文书
学校四风对照检查材料
2014/08/28 职场文书
大学生档案自我鉴定(2篇)
2014/10/14 职场文书
信用卡工资证明范本
2014/10/17 职场文书
机关干部作风建设剖析材料
2014/10/23 职场文书
2014年医院工作总结
2014/11/20 职场文书
2014年体检中心工作总结
2014/12/23 职场文书
会议主持人开场白台词
2015/05/28 职场文书
好员工观后感
2015/06/17 职场文书
拔河比赛新闻稿
2015/07/17 职场文书
校运会宣传稿大全
2015/07/23 职场文书
公司保洁员管理制度
2015/08/04 职场文书
2016年党员读书月活动总结
2016/04/06 职场文书
用python开发一款操作MySQL的小工具
2021/05/12 Python
Win11开始菜单添加休眠选项
2022/04/19 数码科技