layui table 无 resize 事件,需用 mutationobserver 监听 th 元素 style 属性变动来捕获列宽变化,并在 done 回调中为每个 th 初始化观察器,配合 getcomputedstyle 获取准确宽度。

layui table 的 resize 事件根本不存在
Layui 官方 table 模块没有暴露任何「列宽拖拽完成」的回调,resize 事件是很多人搜错关键词后误以为存在的东西。它既不是 layui 的原生事件,也不在文档里——你绑了也永远不会触发。
真实可用的入口只有一个:done 回调函数,但它只在表格初始化、重载、排序等时机执行,不响应列宽变化。
所以别找事件,得自己监听 DOM 变化:
- 列宽拖拽本质是修改了
th元素的width行内样式 - Layui 每次拖完会立刻写入该样式,且不会节流
- 可以用
MutationObserver监听th的style属性变动
用 MutationObserver 捕获列宽变更
这是目前最稳定、不侵入 layui 源码的做法。注意观察目标必须是具体 th 元素,不能只监听整个 thead,否则变动太频繁、难以过滤。
实操建议:
- 在
done回调里遍历所有th,为每个绑定独立的MutationObserver - 只关注
attributes类型变动,并检查是否是style属性 - 用
getComputedStyle读取当前宽度,避免依赖行内width(因为 layui 有时会写成min-width或带单位的字符串) - 加个简单防抖(比如 50ms),防止连续拖拽触发多次
示例片段:
table.render({
elem: '#demo',
url: '/api/list',
done: function(res, curr, count){
const ths = document.querySelectorAll('.layui-table th');
ths.forEach(th => {
const observer = new MutationObserver(mutations => {
mutations.forEach(m => {
if (m.type === 'attributes' && m.attributeName === 'style') {
const width = getComputedStyle(th).width;
console.log('列宽变为:', width); // 这里可存 localStorage 或发请求
}
});
});
observer.observe(th, { attributes: true });
});
}
});
为什么不用 mousemove + mouseup 模拟监听
有人试图监听鼠标在分隔线上的行为,这条路走不通:
- Layui 的列宽拖拽逻辑在闭包里,没暴露句柄,也没加自定义 class 到分隔线上
- 分隔线是伪元素(
::after),无法直接绑定事件 - 即使能捕获
mouseup,你也无法知道它对应哪一列——没有上下文关联 - 移动端不触发
mousemove,兼容性直接归零
所以绕开交互层,直击 DOM 状态变更,才是唯一靠谱路径。
保存和恢复列宽时要注意的坑
如果目的是「记住用户上次调的列宽」,光捕获不够,还得存、还得读、还得注入回去:
- 不要用
col的width配置项硬写死——它只在初始化时生效,后续改无效 - 恢复时得等 table 渲染完再操作
th.style.width,否则被 layui 自动覆盖 - 用
localStorage存时,键名建议带上 table 的id或接口 URL 哈希,避免多个表格互相污染 - 注意单位:layui 写的是
px,但用户可能手动拉出小数,getComputedStyle返回的是带单位的字符串(如"123.456px"),存之前最好parseFloat一下
复杂点在于:列顺序可能变、列可能增删、表头可能有固定列——这些都会让「第 2 列」对应不上上次存的宽度。真要健壮支持,得靠 field 字段名做 key,而不是索引。











