博客 / 詳情

返回

還在痛苦前端的拖拽排序嗎?SortableJS 輕鬆搞定

產品扔過來一個需求:這個列表需要實現拖拽排序,心裏面慌不慌?

如果要手搓一個這個功能,那代碼可就很感人了。

大概有這麼些邏輯:鼠標按下 -> 開始拖動 -> 拖動中實時改變位置 -> 拖動結束判斷是否允許釋放 -> 不允許縮放怎麼做 -> 允許縮放又怎麼做。

要實現這一大堆邏輯,那畫面很美~~


別慌,面向 github 編程,已經有人造了輪子,咱們用起來即可。

SortableJS

項目主頁:https://github.com/SortableJS/Sortable
Star: 12.6k
大小:45.1kB (gzip 17.3kB)
開源協議:MIT

根據官方示例,此插件可以實現這些功能:

  1. 單列表拖拽排序。
  2. 多列表相互拖拽排序。
  3. 通過拖拽克隆複製節點到列表。
  4. 允許 A -> B 拖拽,但 B 不允許拖拽 A
  5. 允許指定拖拽位置,比如只有列表序號能拖拽排序。
  6. 禁止列表某些項拖拽。
  7. 允許設置可放置區域。
  8. 允許嵌套的拖拽排序。

基礎示例

bootcdn 上的 Sortable 魚目混珠的有點多,建議還是從 github 或者 npm 上面下載。

1

源碼:

<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 禁止放入。

2

源碼:

<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 年),估計需要自己填坑。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.