Sortable.js初始化必须传入原生HTMLElement,不可传字符串选择器;常见错误是直接传'#my-list'导致静默失败,正确做法是先用document.getElementById获取元素再初始化。

Sortable.js 初始化时必须传入有效的 DOM 元素
直接传字符串选择器(如 '#my-list')会静默失败,Sortable 构造函数只接受原生 HTMLElement。常见错误是写成 new Sortable('#my-list', {...}),结果拖拽无响应,控制台也不报错。
正确做法是先用 document.querySelector 或 document.getElementById 获取元素:
const el = document.getElementById('my-list');
new Sortable(el, {
animation: 150,
handle: '.handle',
draggable: 'li'
});
- 如果列表是动态渲染的(如 Vue/React 组件挂载后才存在),需确保初始化时机在 DOM 真实插入之后
- 使用
querySelector时注意返回null的情况,建议加空值判断 - 不支持对
DocumentFragment或未挂载的节点初始化
handle 和 draggable 配置不匹配会导致拖拽失效
当设置了 handle 但列表项内没有对应 class,或 draggable 选择器无法命中子元素,整个拖拽逻辑就卡住——光标变手型,但按住无法移动。
典型场景:列表结构为 <ul id="my-list"><li><span class="handle">⋮</span>Item 1</li></ul>
立即学习“前端免费学习笔记(深入)”;
-
handle值应为'.handle'(字符串),不是'.handle span';它指定“拖拽触发区域”,不是目标元素 -
draggable应为'li',表示可被拖动的单位是<li>元素本身 - 若用
draggable: '.item',则每个<li>必须有class="item",否则排序时位置计算异常
onEnd 回调里拿不到实时 DOM 顺序?别直接读 innerHTML
很多人在 onEnd 里用 el.innerHTML 拼接 ID 列表,结果发现顺序和视觉不符——因为 Sortable 内部用的是虚拟排序+CSS transform 位移,DOM 实际顺序可能尚未同步。
- 应使用回调参数中的
evt.item、evt.from、evt.to和evt.oldIndex/evt.newIndex做增量更新 - 如需完整新顺序,用
Array.from(el.children).map(child => child.dataset.id),确保读取的是当前真实 DOM 子节点顺序 - 避免在
onEnd中直接操作大量 DOM 或发起网络请求,可能阻塞拖拽反馈;建议用setTimeout(..., 0)延迟执行副作用
IE11 兼容需手动引入 Polyfill 且禁用 CSS transforms
Sortable 默认启用 transform 动画(animation: 150),但 IE11 对 transform 在 position: static 元素上支持不稳定,拖拽中会出现位置跳变或卡死。
- 必须引入
webcomponentsjs或至少custom-elements-es5-adapter.js(如果用了自定义元素) - 显式关闭硬件加速:
animation: 0,改用fallbackOnBody: true+scroll: true提升滚动体验 - IE11 下
handle点击区域识别更敏感,建议增大handle元素尺寸或加cursor: move


















