Sortable.js 拖拽排序插件使用详解与配置指南

作者:异步漫步

时间:2026-10-22

浏览:572

本文详细介绍轻量级开源 JavaScript 插件 Sortable.js 的使用方法。该插件基于原生 HTML5 拖放 API,支持单列表内部及多列表间拖拽排序,兼容主流浏览器与触屏设备。文章涵盖核心配置项、事件回调、常用方法及动画效果设置,并提供完整代码示例,帮助开发者快速实现高效的列表排序交互。

文章目录

Sortable.js 简介与特性

本文通过具体实例解析 JavaScript 拖拽排序插件 Sortable.js 的使用方式,供读者参考学习。

因项目功能需求,需实现表格行的拖拽排序功能。经过筛选,发现开源库 Sortable.js 能完美契合需求,故整理本文以记录其使用心得。

Sortable.js 具备以下主要特性:

  • 体积小巧且功能丰富。
  • 列表项移动时支持平滑动画效果。
  • 兼容触屏设备以及绝大多数现代浏览器(IE9 及以下版本除外)。
  • 既支持单一列表容器内部的拖拽排序,也支持多个列表容器之间的相互拖拽排序。
  • 兼容拖放操作与文本选择功能。
  • 提供优秀的自动滚动体验。
  • 基于原生 HTML5 拖放 API 构建。
  • 兼容多种前端框架,包括 Angular、Vue、React 等。
  • 完全支持各类 CSS 框架,例如 Bootstrap。
  • API 设计简洁,调用便捷。
  • 提供 CDN 加速支持。
  • 无需依赖 jQuery 即可独立运行。

插件下载与获取

获取方式:访问 GitHub 仓库 https://github.com/RubaXa/Sortable 下载,或点击此处本站链接下载。

运行效果演示

运行效果如图所示:

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:字符串或数组。sort:布尔值,定义列表单元是否可在容器内拖拽排序;delay:数值,定义触发拖动的延迟时间(毫秒);disabled:布尔值,设为 true 时禁用排序功能,设为 false 时启用,相当于开关;animation:数值(毫秒),定义排序动画持续时间;handle:CSS 选择器字符串,指定触发拖动的元素(如标题或按钮),仅按住该区域可拖动;filter:CSS 选择器字符串,定义不可拖动的元素,支持多个选择器以逗号分隔;draggable:CSS 选择器字符串,定义允许拖动的列表单元;ghostClass:CSS 选择器字符串,为拖动时生成的影子副本添加类名,便于自定义样式;chosenClass:CSS 选择器字符串,选中列表单元时添加的类名;forceFallback:布尔值,设为 true 时不使用原生 HTML5 拖放,允许自定义样式;fallbackClass:字符串,forceFallback 为 true 时鼠标附着单元的样式类;scroll:布尔值,默认为 true,当容器可滚动时,拖放操作可触发区域滚动。

事件回调函数:

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

事件对象属性:

各事件中的对象属性略有差异,可通过控制台输出查看。主要属性包括:

to:HTMLElement,目标列表容器;from:HTMLElement,源列表容器;item:HTMLElement,被移动的列表单元;clone:HTMLElement,副本单元;oldIndex:数值或 undefined,原序号;newIndex:数值或 undefined,新序号。

常用方法说明

常用方法:

option(name[,value]) 用于获取或设置项参数。用法类似 jQuery,无第二个参数时获取指定选项的值,有第二个参数时则重新赋值。

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

toArray() 序列化可排序列表单元的 data-id(可通过配置项 dataIdAttr 修改)并返回包含这些 ID 的数组。

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

save()

destroy()

相关工具与资源

此外,推荐一款排序算法演示工具供参考:

在线动画演示插入/选择/冒泡/归并/希尔/快速排序算法过程工具: http://tools.jb51.net/aideddesign/paixu_ys

更多 JavaScript 相关内容可查阅本站专题:《JavaScript表格(table)操作技巧大全》、《JavaScript操作DOM技巧总结》、《JavaScript遍历算法与技巧总结》、《JavaScript数学运算用法总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript查找算法技巧总结》及《JavaScript错误与调试技巧总结》。

希望本文所述内容对大家学习 JavaScript 程序设计有所帮助。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章