產品扔過來一個需求:這個列表需要實現拖拽排序,心裏面慌不慌?
如果要手搓一個這個功能,那代碼可就很感人了。
大概有這麼些邏輯:鼠標按下 -> 開始拖動 -> 拖動中實時改變位置 -> 拖動結束判斷是否允許釋放 -> 不允許縮放怎麼做 -> 允許縮放又怎麼做。
要實現這一大堆邏輯,那畫面很美~~
別慌,面向 github 編程,已經有人造了輪子,咱們用起來即可。
SortableJS
項目主頁:https://github.com/SortableJS/Sortable
Star: 12.6k
大小:45.1kB (gzip 17.3kB)
開源協議:MIT
根據官方示例,此插件可以實現這些功能:
- 單列表拖拽排序。
- 多列表相互拖拽排序。
- 通過拖拽克隆複製節點到列表。
- 允許 A -> B 拖拽,但 B 不允許拖拽 A
- 允許指定拖拽位置,比如只有列表序號能拖拽排序。
- 禁止列表某些項拖拽。
- 允許設置可放置區域。
- 允許嵌套的拖拽排序。
基礎示例
bootcdn 上的 Sortable 魚目混珠的有點多,建議還是從 github 或者 npm 上面下載。

源碼:
<ul class="list" id="sortable">
<li class="item" data-id="item-1">1</li>
<li class="item" data-id="item-2">2</li>
<li class="item" data-id="item-3">3</li>
<li class="item" data-id="item-4">4</li>
</ul>
<style>
.list {
list-style: none;
padding: 0;
width: 300px;
}
.item {
margin: 8px 0;
padding: 8px;
border: 1px solid #999;
color: #fff;
}
</style>
<script src="https://registry.npmmirror.com/sortablejs/1.15.6/files/Sortable.min.js"></script>
<script>
// 初始化
new Sortable(document.getElementById('sortable'), {
animation: 150,
// 結束拖拽
onEnd: function () {
const list = this.toArray()
console.log(JSON.stringify(list));
},
})
</script>
可使用 data-id 屬性自定義元素 ID,方便在 vue 項目中與數據關聯。
多列表互動
使用 group 屬性可對拖拽分組,同一組中的元素允許互動,也可設置 put: false 禁止放入。

源碼:
<ul class="list1" id="sortable1">
<li class="item" data-id="item-1">1</li>
<li class="item" data-id="item-2">2</li>
<li class="item" data-id="item-3">3</li>
<li class="item" data-id="item-4">4</li>
</ul>
<ul class="list2" id="sortable2">
<li class="item" data-id="item-1">1</li>
<li class="item" data-id="item-2">2</li>
<li class="item" data-id="item-3">3</li>
<li class="item" data-id="item-4">4</li>
</ul>
<style>
ul {
list-style: none;
padding: 0;
}
.list1 {
display: flex;
align-items: center;
}
.list1 .item {
padding: 8px 16px;
margin-right: 16px;
border: 1px solid #999;
}
.list2 {
width: 300px;
}
.list2 .item {
margin: 8px 0;
padding: 8px;
border: 1px solid #999;
color: #fff;
}
</style>
<script src="https://registry.npmmirror.com/sortablejs/1.15.6/files/Sortable.min.js"></script>
<script>
new Sortable(document.getElementById('sortable1'), {
group: {
name: 'test-group',
pull: 'clone',
put: false // 不允許拖拽進這個列表
},
animation: 150,
sort: false // 設為false,禁止sort
});
new Sortable(document.getElementById('sortable2'), {
group: 'test-group',
animation: 150
});
</script>
更多使用方式
官方文檔:https://sortablejs.github.io/Sortable/
中文網:https://sortablejs.com/
配置項:https://sortablejs.com/options
npm 安裝
npm install sortablejs --save
使用
// 默認引用
import Sortable from 'sortablejs';
// 模塊化核心代碼,不包含插件
// import Sortable from 'sortablejs/modular/sortable.core.esm.js';
// 模塊化完整代碼,包含所有插件
// import Sortable from 'sortablejs/modular/sortable.complete.esm.js';
// 初始化
new Sortable(document.getElementById('sortable'), {
animation: 150,
// 結束拖拽
onEnd: function () {
const list = this.toArray()
console.log(JSON.stringify(list));
},
})
模塊化引入
import Sortable from 'https://registry.npmmirror.com/sortablejs/1.15.6/files/modular/sortable.complete.esm.js';
// 初始化
new Sortable(document.getElementById('sortable'), {
animation: 150,
// 結束拖拽
onEnd: function () {
const list = this.toArray()
console.log(JSON.stringify(list));
},
})
寫在最後
拖拽排序這需求,一般在交互要求高的項目中,基本上都會遇到,手搓輪子雖然沒啥難度,但實現起來的流程太複雜,基本上都是直接使用開源插件。
如果是 Vue 項目,可參考 https://github.com/SortableJS/Vue.Draggable,雖然都是同一家的代碼,但這插件已年久失修(最近更新 2020 年),估計需要自己填坑。