layui原生tab不支持拖拽排序,需手动绑定drag事件或用sortable.js实现dom重排,并同步更新li、tab-item顺序及layui-this状态。

Layui 原生 tab 组件不支持拖拽调整选项卡左右顺序,也没有内置的 draggable 或 reorder 配置项。所谓“拖拽排序选项卡”,必须通过手动绑定原生拖拽事件(dragstart/dragover/drop)或引入第三方库(如 Sortable.js)来实现 DOM 层的 <li> 元素重排,并同步更新底层数据与选中状态。
核心原理
选项卡的视觉顺序由 .layui-tab-title > li 的 DOM 顺序决定。拖拽目标是这些 <li>,不是整个 .layui-tab 容器。拖拽后需:
- 更新 DOM 中
<li>和对应.layui-tab-content > .layui-tab-item的顺序 - 保持
layui-this类准确落在当前激活项上 - 若有业务数据(如 tab 标签页关联的 ID、URL 或缓存内容),需同步维护映射关系
用原生 drag API 实现(推荐轻量场景)
-
确保 tab 渲染完成后再操作
Layui 初始化 tab 是异步的,需等 DOM 挂载完毕(例如在layui.use回调里加延时或监听DOMContentLoaded):layui.use(['element'], function(){ const element = layui.element; // 等待 DOM 就绪(可配合 setTimeout 或 MutationObserver) setTimeout(() => { initTabDrag(); }, 100); }); -
为每个 tab 标题
<li>添加拖拽能力function initTabDrag() { const $titleList = $('.layui-tab-title'); const $lis = $titleList.children('li'); $lis.each(function() { this.draggable = true; }); $titleList.on('dragstart', 'li', function(e) { e.originalEvent.dataTransfer.setData('text/plain', this.dataset.index || $(this).index()); $(this).addClass('layui-tab-dragging'); }); $titleList.on('dragover', function(e) { e.preventDefault(); // 必须阻止默认行为,否则 drop 不触发 }); $titleList.on('drop', 'li', function(e) { e.preventDefault(); const $target = $(this); const $dragged = $titleList.find('.layui-tab-dragging').removeClass('layui-tab-dragging'); const draggedIndex = parseInt($dragged.data('index') || $dragged.index()); const targetIndex = $target.index(); if (draggedIndex === targetIndex) return; const $allLis = $titleList.children('li'); const $contentItems = $('.layui-tab-content > .layui-tab-item'); // 移动标题 li if (draggedIndex -
补充样式(可选)提升体验
.layui-tab-title .layui-tab-dragging { opacity: 0.6; transition: opacity 0.2s; }
用 Sortable.js 实现(推荐复杂/多端场景)
更稳定、兼容移动端(需额外处理 touch),代码更简洁:
<!-- 引入 Sortable.js --> <script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.0/Sortable.min.js"></script>
layui.use(['element'], function(){
const element = layui.element;
setTimeout(() => {
const el = document.querySelector('.layui-tab-title');
new Sortable(el, {
animation: 150,
handle: 'li', // 只允许点击 li 区域拖拽
onEnd: function(evt) {
const { oldIndex, newIndex } = evt;
const $content = $('.layui-tab-content');
const $items = $content.children('.layui-tab-item');
// 同步移动内容项
if (oldIndex !== newIndex) {
const $moved = $items.eq(oldIndex);
if (oldIndex <blockquote><p>✅ 注意:<code>Sortable</code> 默认不处理 <code>.layui-tab-content</code>,必须手动同步内容区顺序;否则 tab 切换会错位。</p></blockquote><hr><h3><strong>持久化顺序(可选)</strong></h3><p>如果希望刷新页面后仍保留拖拽后的顺序,需自行保存 <code>li</code> 的 <code>lay-id</code> 序列到 <code>localStorage</code>,并在初始化 tab 前按该顺序组织 HTML 或 JS 数据源。</p><pre class="brush:js;toolbar:false;">// 保存
const order = $('.layui-tab-title li').map((i, el) => $(el).attr('lay-id')).get();
localStorage.setItem('tabOrder', JSON.stringify(order));
// 加载(在渲染前)
const saved = localStorage.getItem('tabOrder');
if (saved) {
const ids = JSON.parse(saved);
// 按 ids 顺序重组 tab 数据数组,再传给 tab.render()
}Layui 的 tab 是纯 DOM 结构驱动,没有抽象的数据模型层,所以拖拽本质就是操作 <li> 和 <div> 的顺序,并小心维护 <code>layui-this 和 lay-id 的一致性。不复杂但容易忽略同步内容区这一步。











