Layui表格动态删列必须调用table.reload()传入新cols,直接修改cols数组无效;reload需补全page、where、initSort等参数以保留状态,并手动过滤导出和打印数据。

直接操作 cols 数组会失效,必须 reload 才生效
Layui 的 table.render() 初始化后,cols 是一次性传入的配置,后续对数组的修改(比如 splice()、filter())不会自动反映到表格 UI 上。Layui 不监听数组引用或内容变化,只认你调用 table.reload() 时显式传入的新 cols。
常见错误是:删完 config.cols[0] 里的某列后没 reload,结果页面毫无变化;或者 reload 时漏传关键参数(如 url、page、height),导致分页器重置、高度丢失、甚至 loading 卡住。
- 动态删列的唯一可靠路径:构造新
cols→ 调用table.reload({ cols: 新cols }) - 如果用了
fixed: 'right',确保操作列(如“删除”按钮列)始终在新cols[0]的末尾,否则固定列会错位或消失 - 删列后若要保留排序/筛选状态,reload 时需补传
initSort和当前搜索关键词(where)
怎么识别并剔除“操作列”(如含删除按钮的列)
不能只看 title === '操作' —— 很多项目里“操作”列的 title 是空字符串或“工具”,真正特征在列定义结构里:
- 有
toolbar属性(如toolbar: '#delTpl') -
field为空字符串、null或明显非业务字段名(如'opt'、'handle'、'operate') -
templet函数或字符串中包含lay-event="del"或类似标记
示例:从原始 cols[0] 中移除所有操作意图列
const cleanCols = originalCols[0].filter(col => {
if (col.toolbar) return false;
if (!col.field || ['opt', 'operate', 'handle', 'action'].includes(col.field)) return false;
if (col.templet && /lay-event=["']?del/i.test(typeof col.templet === 'function' ? col.templet({}) : col.templet)) return false;
return true;
});
table.reload({ cols: [cleanCols] });
导出 Excel 时删列和界面删列是两回事
table.exportFile() 默认读取的是 table.cache['your-table-id'] 中的全量原始数据,它完全不关心你界面上隐藏了哪列、cols 里删了什么。所以即使你 reload 后界面上已无“删除”列,导出文件里仍可能带出 data[i].operate 这样的字段。
- 导出前必须手动过滤
data:先从table.cache拿数据,再用map()剔除操作列对应的 key - 别依赖
export: false或 CSSdisplay: none—— 它们对导出无效 - 如果操作列没有
field,但渲染后每条数据对象里仍多了个operate: undefined字段,也要在 map 里解构剔除
打印时去掉某列必须重传 cols,不是 hide
table.print() 不会读取你当前 DOM 的显示状态,也不识别 hideCol。它只按初始化时或你传入的 cols 参数生成打印内容。所以“去掉某列”本质是临时构造一个不含该列的 cols 配置传进去。
- 漏掉
width或align会导致打印列宽异常、文字截断 - 如果原列用了
templet,打印时默认输出纯文本(不执行函数),但要注意返回值是否含 HTML 标签——打印会原样显示字符,不是渲染效果 - 推荐写法:
table.print({ cols: [filteredCols] }),而不是改全局table.config.cols
删列这件事,核心就一条:Layui 不维护“响应式列配置”,所有变更都得靠 reload 或显式传参驱动。最容易被忽略的是——你以为删了 UI 就等于删了数据结构,其实 cache、导出、打印各走各的路,一步不跟,全盘失效。











