快速开始
快速开始 使用 NPM 安装:
css
npm install sortablejs --save
使用 Bower 安装:
css
bower install --save sortablejs
导入到您的项目中:
javascript
// 默认的 SortableJS
import Sortable from 'sortablejs';
// 核心 SortableJS (不含默认插件)
import Sortable from 'sortablejs/modular/sortable.core.esm.js';
// 完整的 SortableJS (包含所有插件)
import Sortable from 'sortablejs/modular/sortable.complete.esm.js';
挑选插件:
javascript
// 挑选额外的插件
import Sortable, { MultiDrag, Swap } from 'sortablejs';
Sortable.mount(new MultiDrag(), new Swap());
// 挑选默认插件
import Sortable, { AutoScroll } from 'sortablejs/modular/sortable.core.esm.js';
Sortable.mount(new AutoScroll());
用法
xml
<ul id="items">
<li>项目 1</li>
<li>项目 2</li>
<li>项目 3</li>
</ul>
ini
var el = document.getElementById('items');
var sortable = Sortable.create(el,Options);
您可以使用任何元素作为列表及其元素,而不仅仅是 ul
和 li
。这里有一个使用 div
的例子。
📋 配置项 (Options)
基础配置
配置项 | 类型 | 默认值 | 说明 |
---|---|---|---|
group |
String/Object | "default" |
分组名称,相同分组可以互相拖拽 |
sort |
Boolean | true |
是否允许在列表内排序 |
disabled |
Boolean | false |
是否禁用拖拽功能 |
store |
Object | null |
存储配置,用于保存和恢复排序状态 |
animation |
Number | 0 |
动画持续时间(毫秒) |
easing |
String | null |
动画缓动函数,如 "cubic-bezier(1, 0, 0, 1)" |
handle |
String | null |
拖拽手柄选择器,只有点击此元素才能拖拽 |
filter |
String/Function | null |
过滤器,匹配的元素不可拖拽 |
preventOnFilter |
Boolean | true |
触发过滤器时是否阻止默认事件 |
draggable |
String | null |
可拖拽元素的选择器 |
dataIdAttr |
String | "data-id" |
元素ID的数据属性名 |
ghostClass |
String | "sortable-ghost" |
拖拽占位符的CSS类名 |
chosenClass |
String | "sortable-chosen" |
被选中元素的CSS类名 |
dragClass |
String | "sortable-drag" |
拖拽中元素的CSS类名 |
swapThreshold |
Number | 1 |
交换阈值,0-1之间的值 |
invertSwap |
Boolean | false |
是否反转交换逻辑 |
invertedSwapThreshold |
Number | null |
反转交换的阈值 |
direction |
String | null |
排序方向:"vertical"、"horizontal" 或自动检测 |
forceFallback |
Boolean | false |
强制使用HTML5拖拽的备用方案 |
fallbackClass |
String | "sortable-fallback" |
备用拖拽元素的CSS类名 |
fallbackOnBody |
Boolean | false |
将备用元素附加到body |
fallbackTolerance |
Number | 0 |
备用模式下的鼠标移动容差(像素) |
fallbackOffset |
Object | {x: 0, y: 0} |
备用元素的偏移量 |
supportPointer |
Boolean | true |
是否支持Pointer Events |
emptyInsertThreshold |
Number | 5 |
空容器的插入阈值(像素) |
滚动相关配置
配置项 | 类型 | 默认值 | 说明 |
---|---|---|---|
scroll |
Boolean/Element | true |
是否启用自动滚动 |
scrollFn |
Function | null |
自定义滚动函数 |
scrollSensitivity |
Number | 30 |
触发滚动的边距(像素) |
scrollSpeed |
Number | 10 |
滚动速度 |
bubbleScroll |
Boolean | true |
是否允许滚动冒泡到父容器 |
forceAutoScrollFallback |
Boolean | false |
强制使用自动滚动的备用方案 |
多选相关配置
配置项 | 类型 | 默认值 | 说明 |
---|---|---|---|
multiDrag |
Boolean | false |
是否启用多选拖拽 |
selectedClass |
String | "sortable-selected" |
选中项的CSS类名 |
multiDragKey |
String | null |
多选按键:"ctrl"、"alt"、"shift" |
avoidImplicitDeselect |
Boolean | false |
避免隐式取消选择 |
分组配置详细说明
当 group
为对象时,可以包含以下属性:
sql
group: {
name: "shared", // 分组名称
pull: true, // 是否可以从此列表拖拽出元素 (true/false/function/"clone")
put: true, // 是否可以放入元素到此列表 (true/false/function/array)
revertClone: false // 克隆模式下是否还原克隆元素
}
🛠️ 方法 (Methods)
实例方法
方法名 | 参数 | 返回值 | 说明 |
---|---|---|---|
option(name, value?) |
name: String, value?: Any | Any | 获取或设置配置项 |
closest(el, selector?) |
el: Element, selector?: String | Element | 查找最近的匹配元素 |
toArray() |
- | String[] | 获取元素的data-id数组 可通过配置项dataIdAttr修改放入一个数组,并返回这个数组中 |
sort(order, useAnimation?) |
order: String[], useAnimation?: Boolean | void | 按指定顺序排序元素 |
save() |
- | void | 保存当前排序状态 |
destroy() |
- | void | 销毁Sortable实例 |
静态方法
方法名 | 参数 | 返回值 | 说明 |
---|---|---|---|
Sortable.create(el, options?) |
el: Element, options?: Object | Sortable | 创建Sortable实例 |
Sortable.get(el) |
el: Element | Sortable | 获取元素的Sortable实例 |
Sortable.mount(...plugins) |
...plugins: Plugin[] | void | 挂载插件 |
Sortable.utils |
- | Object | 实用工具集合 |
工具方法 (Sortable.utils)
方法名 | 参数 | 返回值 | 说明 |
---|---|---|---|
on(el, event, fn) |
el: Element, event: String, fn: Function | void | 添加事件监听器 |
off(el, event, fn) |
el: Element, event: String, fn: Function | void | 移除事件监听器 |
css(el, prop, val?) |
el: Element, prop: String, val?: String | String/void | 获取或设置CSS属性 |
find(ctx, tagName, iterator?) |
ctx: Element, tagName: String, iterator?: Function | Element[] | 查找子元素 |
bind(ctx, fn) |
ctx: Object, fn: Function | Function | 绑定上下文 |
is(el, selector) |
el: Element, selector: String | Boolean | 检查元素是否匹配选择器 |
closest(el, selector, ctx?) |
el: Element, selector: String, ctx?: Element | Element | 查找最近的匹配祖先元素 |
clone(el) |
el: Element | Element | 克隆元素 |
toggleClass(el, name, state?) |
el: Element, name: String, state?: Boolean | void | 切换CSS类 |
detectDirection(el) |
el: Element | String | 检测排列方向 |
📢 事件 (Events)
拖拽生命周期事件
事件名 | 触发时机 | 参数说明 |
---|---|---|
onChoose |
选择元素开始拖拽时 | evt.oldIndex - 原始索引 |
onUnchoose |
取消选择元素时 | evt.oldIndex - 原始索引 |
onStart |
开始拖拽时 | evt.oldIndex - 原始索引 |
onEnd |
拖拽结束时 | evt.oldIndex - 原始索引 evt.newIndex - 新索引 |
onAdd |
元素被添加到列表时 | evt.newIndex - 新索引 evt.item - 被添加的元素 |
onUpdate |
元素在列表内移动时 | evt.oldIndex - 原始索引 evt.newIndex - 新索引 |
onSort |
任何排序发生时 | evt.oldIndex - 原始索引 evt.newIndex - 新索引 |
onRemove |
元素被移除时 | evt.oldIndex - 原始索引 evt.item - 被移除的元素 |
onFilter |
尝试拖拽被过滤的元素时 | evt.item - 被过滤的元素 |
onMove |
拖拽移动过程中 | evt.dragged - 被拖拽的元素 evt.draggedRect - 拖拽元素的位置信息 evt.related - 相关元素 evt.relatedRect - 相关元素的位置信息 evt.willInsertAfter - 是否在后面插入 |
onClone |
克隆元素时 | evt.item - 原始元素 evt.clone - 克隆的元素 |
onChange |
拖拽导致列表改变时 | evt.newIndex - 新索引 evt.oldIndex - 原始索引 |
事件对象属性详解
每个事件回调函数都会接收一个事件对象,包含以下属性:
javascript
{
to: HTMLElement, // 目标列表元素
from: HTMLElement, // 源列表元素
item: HTMLElement, // 被拖拽的元素
clone: HTMLElement, // 克隆的元素(如果有)
oldIndex: Number, // 在源列表中的索引
newIndex: Number, // 在目标列表中的索引
oldDraggableIndex: Number, // 在可拖拽元素中的索引
newDraggableIndex: Number, // 在可拖拽元素中的新索引
pullMode: String, // 拉取模式 ("clone"/"true")
originalEvent: Event // 原始浏览器事件
}
💡 使用示例
基础配置示例
less
var sortable = Sortable.create(document.getElementById('items'), {
// 基础配置
group: 'shared',
animation: 150,
// 样式类名
ghostClass: 'sortable-ghost',
chosenClass: 'sortable-chosen',
dragClass: 'sortable-drag',
// 拖拽限制
handle: '.drag-handle',
filter: '.no-drag',
// 滚动配置
scroll: true,
scrollSensitivity: 30,
scrollSpeed: 10,
// 事件处理
onStart: function(evt) {
console.log('开始拖拽:', evt.oldIndex);
},
onEnd: function(evt) {
console.log('拖拽结束:', evt.oldIndex, '->', evt.newIndex);
},
onMove: function(evt) {
// 自定义移动逻辑
return true; // 返回false阻止移动
}
});
高级分组配置示例
php
// 源列表(只能拖出,不能拖入)
Sortable.create(sourceList, {
group: {
name: 'shared',
pull: 'clone', // 克隆模式拖出
put: false // 不允许拖入
}
});
// 目标列表(只能拖入,不能拖出)
Sortable.create(targetList, {
group: {
name: 'shared',
pull: false, // 不允许拖出
put: true // 允许拖入
}
});
方法调用示例
csharp
// 获取排序数组
var order = sortable.toArray();
// 按指定顺序排序
sortable.sort(['item-1', 'item-3', 'item-2']);
// 获取配置项
var animationDuration = sortable.option('animation');
// 设置配置项
sortable.option('disabled', true);
// 销毁实例
sortable.destroy();
🔌 插件系统
SortableJS 支持插件扩展,常用插件包括:
- MultiDrag - 多选拖拽插件
- Swap - 交换模式插件
- AutoScroll - 自动滚动插件
php
// 加载插件
Sortable.mount(new MultiDragPlugin(), new SwapPlugin());
// 使用插件功能
var sortable = Sortable.create(el, {
multiDrag: true,
selectedClass: 'selected'
});
📝 注意事项
- 性能优化:对于大量元素,建议使用虚拟滚动或分页
- 移动端适配 :在移动设备上可能需要设置
forceFallback: true
- 内存管理 :记得在不需要时调用
destroy()
方法 - 事件冒泡:注意事件可能会冒泡,需要适当处理
- CSS样式:确保拖拽相关的CSS类有正确的样式定义