layui table 原生不保存列宽,需手动监听 mouseup 实现拖拽结束存 localstorage,key 用 table-${tableid}-${field},value 存纯数字 px 值,并在 cols 初始化时通过 minwidth 覆盖生效,避免在 done 回调中直接改样式。
layui table 本身不保存列宽,拖完就丢——这不是 bug,是设计如此。要记住宽度,必须自己监听拖拽结束、存 localstorage、再在下一次渲染前读出来覆盖配置。
拖拽列宽后怎么触发保存逻辑
layui 原生不提供 moveEnd 或 resizeEnd 回调,所有“拖完就存”的行为都得靠手动监听 mouseup + DOM 位置判断实现。核心是在表头 th 右侧插入透明拖拽条(div.layui-table-resize),然后:
- 在
mousedown时记录初始列宽、鼠标 X 坐标、对应列的field和lay-id - 在
mousemove中动态计算新宽度(避免直接改th.style.width) - 在
mouseup时把最终宽度写入localStorage,key 建议带表格唯一 ID 和列 field,例如:localStorage.setItem('table-user-list-username', '150') - 必须加
event.preventDefault(),否则会触发文字选中或浏览器默认拖拽
存到 localStorage 的 key 和 value 怎么设计才不冲突
多个表格共用一个页面时,光用列名(如 username)当 key 会串号。正确做法是组合唯一标识:
- key 格式推荐:
table-${tableId}-${field},其中tableId来自table.render({ id: 'user-list' }) - value 存纯数字(单位 px),不要带
px后缀,方便后续计算和校验 - 如果表格启用了固定列(
fixed: 'left'),建议额外加个 flag,比如table-user-list-username-fixed-left,避免左右固定列宽度互相覆盖 - 避免用
window.location.href当 key 主体——URL 带查询参数时容易重复存多份
下次渲染时如何把缓存宽度生效到列配置中
不能等 done 回调再改,那时 DOM 已渲染,硬塞 width 样式会导致排序图标错位、导出列宽不对。必须在 cols 初始化阶段就注入:
- 渲染前先读缓存:
const savedWidth = localStorage.getItem('table-user-list-username') - 遍历原始
cols数组,找到field === 'username'的列,仅覆盖其minWidth(不是width),例如:{ field: 'username', title: '用户名', minWidth: parseInt(savedWidth) || 120 } - 注意:只覆盖
minWidth,不动title、sort、templet等其他配置,否则可能破坏筛选、排序逻辑 - 如果用户没拖过,
savedWidth是null,务必 fallback 到原始默认值
哪些地方最容易被忽略导致“存了但没生效”
最常踩的坑不在拖拽逻辑本身,而在缓存与渲染时机、以及列宽变更后的连锁反应:
- 在
done回调里用$('th').css('width', ...)强行改样式 → 排序箭头偏移、响应式折叠失效、Excel 导出仍是默认宽 - 用
table.cache或table.getData()读宽度 → 这两个 API 返回的是数据,不是列配置,根本没存宽度信息 - 没处理固定列(
fixed: 'left'或fixed: 'right')→ 拖拽条位置错、minWidth更新错列、右侧固定列被左侧遮挡 - 没设宽度下限(如
Math.max(60, newWidth))→ 拖到 5px,内容全看不见,且后续无法再拖回来 - 移动端 touch 事件没兼容 →
mousedown/mousemove在 iOS 上不触发,得补touchstart/touchmove
真正麻烦的不是“怎么存”,而是“存完之后,排序图标、筛选下拉、导出 Excel、响应式折叠、固定列对齐——这些全得跟着动”。没有银弹,每个环节都得单独对齐逻辑。











