冯丹 發表於 2025-12-18 10:08:00

还在痛苦前端的拖拽排序吗?SortableJS 轻松搞定

<p>产品扔过来一个需求:这个列表需要实现拖拽排序,心里面慌不慌?</p>
<p>如果要手搓一个这个功能,那代码可就很感人了。</p>
<p>大概有这么些逻辑:鼠标按下 -&gt; 开始拖动 -&gt; 拖动中实时改变位置 -&gt; 拖动结束判断是否允许释放 -&gt; 不允许缩放怎么做 -&gt; 允许缩放又怎么做。</p>
<p>要实现这一大堆逻辑,那画面很美~~</p>
<hr>
<p>别慌,面向 github 编程,已经有人造了轮子,咱们用起来即可。</p>
<h2 id="sortablejs">SortableJS</h2>
<p>项目主页:https://github.com/SortableJS/Sortable<br>
Star: 12.6k<br>
大小:45.1kB (gzip 17.3kB)<br>
开源协议:MIT</p>
<p>根据官方示例,此插件可以实现这些功能:</p>
<ol>
<li>单列表拖拽排序。</li>
<li>多列表相互拖拽排序。</li>
<li>通过拖拽克隆复制节点到列表。</li>
<li>允许 A -&gt; B 拖拽,但 B 不允许拖拽 A</li>
<li>允许指定拖拽位置,比如只有列表序号能拖拽排序。</li>
<li>禁止列表某些项拖拽。</li>
<li>允许设置可放置区域。</li>
<li>允许嵌套的拖拽排序。</li>
</ol>
<h3 id="基础示例">基础示例</h3>
<p>bootcdn 上的 Sortable 鱼目混珠的有点多,建议还是从 github 或者 npm 上面下载。</p>
<p><img src="https://img2024.cnblogs.com/blog/596097/202512/596097-20251218100735861-176858278.gif"></p>
<p>源码:</p>
<pre><code class="language-html">&lt;ul class="list" id="sortable"&gt;
&lt;li class="item" data-id="item-1"&gt;1&lt;/li&gt;
&lt;li class="item" data-id="item-2"&gt;2&lt;/li&gt;
&lt;li class="item" data-id="item-3"&gt;3&lt;/li&gt;
&lt;li class="item" data-id="item-4"&gt;4&lt;/li&gt;
&lt;/ul&gt;

&lt;style&gt;
.list {
    list-style: none;
    padding: 0;
    width: 300px;
}
.item {
    margin: 8px 0;
    padding: 8px;
    border: 1px solid #999;
    color: #fff;
}
&lt;/style&gt;

&lt;script src="https://registry.npmmirror.com/sortablejs/1.15.6/files/Sortable.min.js"&gt;&lt;/script&gt;
&lt;script&gt;
// 初始化
new Sortable(document.getElementById('sortable'), {
animation: 150,
// 结束拖拽
onEnd: function () {
    const list = this.toArray()
    console.log(JSON.stringify(list));
},
})
&lt;/script&gt;
</code></pre>
<p>可使用 <code>data-id</code> 属性自定义元素 ID,方便在 vue 项目中与数据关联。</p>
<h3 id="多列表互动">多列表互动</h3>
<p>使用 <code>group</code> 属性可对拖拽分组,同一组中的元素允许互动,也可设置 <code>put: false</code> 禁止放入。</p>
<p><img src="https://img2024.cnblogs.com/blog/596097/202512/596097-20251218100741530-1129201655.gif"></p>
<p>源码:</p>
<pre><code class="language-html">&lt;ul class="list1" id="sortable1"&gt;
&lt;li class="item" data-id="item-1"&gt;1&lt;/li&gt;
&lt;li class="item" data-id="item-2"&gt;2&lt;/li&gt;
&lt;li class="item" data-id="item-3"&gt;3&lt;/li&gt;
&lt;li class="item" data-id="item-4"&gt;4&lt;/li&gt;
&lt;/ul&gt;
&lt;ul class="list2" id="sortable2"&gt;
&lt;li class="item" data-id="item-1"&gt;1&lt;/li&gt;
&lt;li class="item" data-id="item-2"&gt;2&lt;/li&gt;
&lt;li class="item" data-id="item-3"&gt;3&lt;/li&gt;
&lt;li class="item" data-id="item-4"&gt;4&lt;/li&gt;
&lt;/ul&gt;

&lt;style&gt;
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;
}
&lt;/style&gt;

&lt;script src="https://registry.npmmirror.com/sortablejs/1.15.6/files/Sortable.min.js"&gt;&lt;/script&gt;
&lt;script&gt;
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
});
&lt;/script&gt;
</code></pre>
<h3 id="更多使用方式">更多使用方式</h3>
<p>官方文档:https://sortablejs.github.io/Sortable/</p>
<p>中文网:https://sortablejs.com/<br>
配置项:https://sortablejs.com/options</p>
<h2 id="npm-安装">npm 安装</h2>
<pre><code class="language-bash">npm install sortablejs --save
</code></pre>
<p>使用</p>
<pre><code class="language-js">// 默认引用
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));
},
})
</code></pre>
<h3 id="模块化引入">模块化引入</h3>
<pre><code class="language-js">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));
},
})
</code></pre>
<h2 id="写在最后">写在最后</h2>
<p>拖拽排序这需求,一般在交互要求高的项目中,基本上都会遇到,手搓轮子虽然没啥难度,但实现起来的流程太复杂,基本上都是直接使用开源插件。</p>
<p>如果是 Vue 项目,可参考 https://github.com/SortableJS/Vue.Draggable,虽然都是同一家的代码,但这插件已年久失修(最近更新 2020 年),估计需要自己填坑。</p>


</div>
<div id="MySignature" role="contentinfo">
    <p>&nbsp;</p>
<p style="font-size: 18px;font-weight: bold;">文章首发于微信公众号【<span style="color:rgb(255, 71, 87)">前端路引</span>】,欢迎 <span style="color:#4ec259">微信扫一扫</span> 查看更多文章。</p>
<p>
<img style="max-width: 320px;" src="https://images.cnblogs.com/cnblogs_com/linx/2447020/o_250228035031_%E5%85%AC%E4%BC%97%E5%8F%B7%E4%BA%8C%E7%BB%B4%E7%A0%81.png"/>
</p>
<p>本文来自博客园,作者:前端路引,转载请注明原文链接:https://www.cnblogs.com/linx/p/19365355</p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/linx/p/19365355
頁: [1]
查看完整版本: 还在痛苦前端的拖拽排序吗?SortableJS 轻松搞定