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 ajax实现下拉框三级无刷新联动,且保存保持选中值状态
Oct 29 Javascript
bootstrapfileinput实现文件自动上传
Nov 08 Javascript
jQuery Validate验证表单时多个name相同的元素只验证第一个的解决方法
Dec 24 Javascript
setTimeout学习小结
Feb 08 Javascript
AngularJS Toaster使用详解
Feb 24 Javascript
js实现城市级联菜单的2种方法
Jun 23 Javascript
jQuery动画_动力节点节点Java学院整理
Jul 04 jQuery
Angularjs的键盘事件的绑定
Jul 27 Javascript
jQuery简单实现的HTML页面文本框模糊匹配查询功能完整示例
May 09 jQuery
微信小程序自定义toast弹窗效果的实现代码
Nov 15 Javascript
通过实例了解Render Props回调地狱解决方案
Nov 04 Javascript
canvas多重阴影发光效果实现
Apr 20 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
全国FM电台频率大全 - 12 安徽省
2020/03/11 无线电
WIN8.1下搭建PHP5.6环境
2015/04/29 PHP
详解WordPress开发中过滤属性以及Sql语句的函数使用
2015/12/25 PHP
yii2使用ajax返回json的实现方法
2016/05/14 PHP
Ext 今日学习总结
2010/09/19 Javascript
Jquery index()方法 获取相应元素索引值
2012/10/12 Javascript
js禁止document element对象选中文本实现代码
2013/03/21 Javascript
js判断背景图片是否加载成功使用img的width实现
2013/05/29 Javascript
jquery 检测元素是否存在的实例代码
2013/11/19 Javascript
JavaScript中判断页面关闭、页面刷新的实现代码
2014/08/27 Javascript
javascript事件委托的方式绑定详解
2015/06/10 Javascript
js实现纯前端的图片预览
2016/04/27 Javascript
JS中的hasOwnProperty()和isPrototypeOf()属性实例详解
2016/08/11 Javascript
JS时间控制实现动态效果的实例讲解
2017/07/31 Javascript
SVG动画vivus.js库使用小结(实例代码)
2017/09/14 Javascript
ES6中字符串string常用的新增方法小结
2017/11/07 Javascript
解决vue keep-alive 数据更新的问题
2018/09/21 Javascript
vue如何搭建多页面多系统应用
2020/06/17 Javascript
通过实例了解JS执行上下文运行原理
2020/06/17 Javascript
js实现点击烟花特效
2020/10/14 Javascript
[01:37]DOTA2超级联赛专访ChuaN 传奇般的电竞之路
2013/06/19 DOTA
[40:17]2018DOTA2亚洲邀请赛 4.5 淘汰赛 LGD vs Liquid 第一场
2018/04/06 DOTA
详解supervisor使用教程
2017/11/21 Python
python使用Pycharm创建一个Django项目
2018/03/05 Python
Python中shapefile转换geojson的示例
2019/01/03 Python
python实现一个猜拳游戏
2020/04/05 Python
用css3实现当鼠标移进去时当前亮其他变灰效果
2014/04/08 HTML / CSS
HTML5混合开发二维码扫描以及调用本地摄像头
2017/12/27 HTML / CSS
英国最大的在线运动补充剂商店:Discount Supplements
2017/06/03 全球购物
KENZO官网:高田贤三在法国创立的品牌
2019/05/16 全球购物
财务管理专业推荐信
2013/11/19 职场文书
优秀士兵先进事迹
2014/02/06 职场文书
个人投资计划书
2014/05/01 职场文书
自主招生自荐信范文
2015/03/04 职场文书
Springboot中如何自动转JSON输出
2022/06/16 Java/Android
Promise静态四兄弟实现示例详解
2022/07/07 Javascript