SortableJS
定义
SortableJS 是一个以 JavaScript 编写的浏览器端库,为列表、表格行、网格等容器提供可重排序的拖放交互;它对条目的移动、占位、动画和事件回调直接负责,开发者只需给容器绑定一次实例[1]。库本身不依赖 jQuery,也不与特定框架绑定,官方说明其可用于 Meteor、AngularJS、React、Vue、Knockout 以及 Bootstrap 等 CSS 框架环境[1]。
包名为 sortablejs,导出的主对象名为 Sortable,同时提供 TypeScript 类型定义包 @types/sortablejs 供类型检查使用[4]。项目以 MIT 许可证发布,允许商用、修改与再分发,条件是在副本中保留版权与许可声明[5]。
原理
库的默认拖动实现建立在浏览器原生的 HTML5 拖放接口之上,例如在 dragstart 阶段通过 dataTransfer 携带被拖条目的数据[1]。原生接口在旧浏览器与部分移动设备上行为不一致,因此库内另有一套回退模式:把被拖元素复制一份浮在页面上跟随指针,并在原位置留下一个带 ghostClass 的占位元素,其余条目依靠 CSS 过渡让出位置[1]。选项 forceFallback 可以强制走回退模式,fallbackTolerance 则用来设定指针移动多少像素后才算开始拖动,以免单击被误判为拖动[1]。
是否需要插入由位置判定得出。拖动过程中库持续比较指针与被覆盖条目的矩形区域,可交换区域的大小由 swapThreshold 控制,取值为 0 到 1 之间的小数;当命中比例为 $t$ 的区域时,条目即在此处插入或与之互换[1]。交换区的方向可由 direction 指定为垂直或水平,invertSwap 则把交换区移到目标条目两侧以形成插到两者之间的效果[1]。跨列表拖动依赖 group 机制:两个容器只要名称相同,即可互相接收条目,pull 与 put 分别控制一个列表能否向外拖出、能否接收拖入[1]。
每次拖动结束后回调会给出一个事件对象,其中 from 与 to 指向来源容器和目标容器,item 指向被拖元素,oldIndex 与 newIndex 分别是它在原父节点和新父节点中的序号,clone 与 pullMode 用于区分移动和克隆[1]。onSort、onAdd、onUpdate、onRemove 等回调覆盖了列表的一切变化类型,toArray 方法可以按 dataIdAttr 指定的属性把当前顺序读成字符串数组,sort 方法则按给定数组重新排列条目[1]。
发展历程
项目由列别杰夫·康斯坦丁创建,其代码托管仓库最初位于 RubaXa 名下,MIT 许可声明中的版权年份写作 2013 年至 2016 年,说明最早的发布可追溯到 2013 年[6]。此后仓库迁至 SortableJS 组织下,早期版本的接口即以 Sortable.create 创建实例,并可选用 new Sortable 的构造写法[7]。
版本发布记录显示 0.7.0 与 1.0.0 两个版本均在 2014 年 12 月发布,此后进入 1.x 系列[2]。1.8.0 版本重写了 dragover 相关逻辑,新增 direction、swapThreshold、invertSwap、invertedSwapThreshold 等选项,并修正了原生拖放下的占位元素尺寸与定位问题,同时改变了回退模式下 dragstart 相关事件的触发时机以与原生行为对齐[8]。
2022 年 3 月发布 1.15.0,2024 年 11 月间连续发布 1.15.4、1.15.5、1.15.6 三个补丁版本,2026 年 2 月 11 日发布 1.15.7,累计发布版本数为 38 个[2]。同一时期仓库关注量超过 3.1 万,未关闭的议题数量在 520 条以上,最近一次代码推送发生在 2026 年 3 月[5]。
应用
最常见的用法是给列表或表格容器添加可排序能力。在 Vue 3 与 Element Plus 的表格组件中,需要先定位到表格主体内部的 tbody 元素,再以其为根创建实例,并在拖动结束的回调里依据 oldIndex 与 newIndex 调整数据数组的次序,使视图与数据保持一致[9]。Web 前端实践中,它常被用于任务清单调整优先级、图片编辑器中调整布局、内容管理后台调整条目顺序等场景[10]。
在框架生态中,VueUse 的集成包提供了 useSortable 封装,可从模板引用或选择器取得根元素,把响应式数组与实例绑定,并暴露 start、stop 与 option 三个方法用于启动、销毁和读写选项[11]。插件机制用于扩展核心功能:MultiDrag 允许一次选中多个条目并成组拖动,Swap 把排序改为两个条目互换位置,AutoScroll 负责拖到容器边缘时的自动滚动,插件通过 Sortable.mount 挂载[12][5]。项目提供默认、核心与完整三种构建,核心版本不含默认插件,便于按需控制打包体积[5]。
局限
库的作用范围限于 DOM 层,它改写的是元素在容器中的实际顺序,并不会自动更新前端框架持有的数据模型,因此开发者必须在 onUpdate、onEnd 等回调中自行同步数组,否则视图与数据会出现错位[9]。原生 HTML5 拖放对拖动图像的控制能力有限,某些场景下条目回弹动画会指向初始位置而非新位置,可行的规避方式是启用 forceFallback 或在 dragstart 阶段替换拖动图像[13]。
部分选项存在浏览器前提条件:官方文档说明受浏览器限制,在 IE 或 Edge 使用原生拖放时无法通过 delay 设置延迟启动排序[1]。按轴限制拖动(仅在单一方向移动)这类需求,维护者以原生拖放不支持为由未予采纳,需要自行派生修改[14]。条目数量很大时,拖动的占位元素动画可能出现抖动,社区给出的思路包括只渲染可见区域的虚拟滚动、延迟初始化以及限制 onMove 等高频事件的调用频率[15][16]。
第三方封装未必覆盖全部能力,例如 VueUse 的 useSortable 目前只对单个列表提供拖放排序,并且因为没有导入带插件的完整包,Swap 与 MultiDrag 的选项在其中不会生效[11][17]。此外项目更新节奏并不均匀,1.15.7 之后的一段时间内没有新版本标签,未处理议题数量较多,采用者需对后续维护投入有所准备[5]。
参见
-
HTML5 拖放 API —— 库的默认拖动模式所依赖的浏览器原生接口。
-
Vue.js —— 常与 SortableJS 配合实现表格与列表拖拽排序的前端框架。
-
VueUse —— 提供 useSortable 封装的 Vue 组合式函数集合。
-
npm —— 该库以 sortablejs 为包名发布和分发的软件仓库。
-
MIT 许可证 —— 该项目采用的宽松开源许可协议。
参考资料
- Demo: https://jsbin [引用日期2026-10-29]
- javascripts.com 上的网页 [引用日期2026-10-29]
- sortablejs | Snyk [引用日期2026-10-29]
- @types/sortablejs [引用日期2026-10-29]
- Sortable: drag-and-drop lists, one option at a time [引用日期2026-10-29]
- Sortable [引用日期2026-10-29]
- 拖放排序插件Sortable.js [引用日期2026-10-29]
- sortablejs 1.8.0 on Node.js NPM - sortablejs 1.8.0 v1.8.0 [引用日期2026-10-29]
- 使用Sortable.js库 实现Vue3 elementPlus 的 el-table 拖拽排序 [引用日期2026-10-29]
- js列表拖动排序 [引用日期2026-10-29]
- VueUse [引用日期2026-10-29]
- sortable_js and rank_list [引用日期2026-10-29]
- github.com 上的网页 [引用日期2026-10-29]
- Axis (x,y) wanted · Issue #774 · SortableJS/Sortable [引用日期2026-10-29]
- github.com 上的网页 [引用日期2026-10-29]
- Sortable.js:现代前端拖放交互解决方案详解 [引用日期2026-10-29]
- github.com 上的网页 [引用日期2026-10-29]