Layui table.exportFile 导出时需用 parseData 钩子预处理数据以剥离 HTML 标签,确保纯文本导出;CSV 需手动添加 UTF-8 BOM 头(\ufeff)防乱码;禁用正则全局删标签,应按字段语义分列清洗。
导出时表格单元格含HTML标签,怎么自动剥离
layui 的 table.exportfile 默认把单元格的 innerhtml 当成文本导出,所以带 <span>、<button> 或自定义模板渲染的内容会原样写进 excel/csv,导致数据错乱或格式污染。
根本原因不是导出功能“坏了”,而是 Layui 导出逻辑不解析 DOM,只取 td.innerHTML —— 你渲染了什么,它就导出什么。
- 如果你用
templet返回带标签的字符串(比如'<span class="tag">' + d.status + '</span>'),导出时就会包含这些标签 - 如果列是纯文本但用了
style或class包裹(如<div class="text-ellipsis">xxx</div>),同样会被导出为 HTML 源码 - 服务端导出不受影响,但前端导出(
exportFile)必须在客户端预处理
用 parseData 在导出前清洗 cell 内容
parseData 是 Layui 表格导出时唯一能拦截并修改原始数据的钩子,它在生成文件前执行,返回的对象字段会直接作为导出值。
关键点:它接收的是原始数据对象 d,不是 DOM;你要在这个函数里手动构造「干净文本」,而不是依赖单元格渲染结果。
- 不要试图在
templet里加判断“导出时返回纯文本”——templet只控制渲染,不影响导出 - 必须在
table.render()配置中显式传入parseData函数,且返回值结构要和表头字段严格对应 - 如果某列用了
templet渲染图标或状态色块,parseData里就得用相同逻辑从d中提取纯文本(比如d.status === 'success' ? '成功' : '失败')
table.render({
elem: '#demo',
data: [...],
cols: [[
{field: 'title', title: '标题'},
{field: 'status', title: '状态', templet: '<div class="layui-badge">{{d.status}}</div>'}
]],
parseData: function(res){
return {
data: res.data.map(function(d){
return {
title: d.title || '',
status: d.status === 'success' ? '成功' : d.status === 'fail' ? '失败' : d.status
};
})
};
}
});
导出 CSV 时中文乱码?别漏掉 BOM 头
即使内容已清洗干净,Windows Excel 打开 CSV 仍可能显示乱码,这不是 HTML 标签问题,而是编码标识缺失。
立即学习“前端免费学习笔记(深入)”;
Layui exportFile 默认输出 UTF-8 字节流,但 Excel(尤其旧版)需要开头有 UTF-8 BOM(\ufeff)才识别为 UTF-8。
- 导出类型设为
csv时,必须在parseData返回的数据之外,额外用done回调劫持导出过程,手动注入 BOM - Excel 打开 XLSX 不受影响,但 CSV 场景下这个细节几乎必踩
- 不能靠后端加 BOM —— 前端导出走的是 Blob 下载,BOM 必须由前端拼接
做法是在调用 table.exportFile 前,先用 table.cache 拿到当前页数据,清洗后转 CSV 字符串,并在开头加 '\ufeff':
var csv = '\ufeff' + '标题,状态\r\n' + data.map(d =>
'"' + d.title.replace(/"/g,'""') + '","' + d.status.replace(/"/g,'""') + '"'
).join('\r\n');
var blob = new Blob([csv], {type: 'text/csv;charset=utf-8'});
layui.$('<a>').attr('href', URL.createObjectURL(blob))
.attr('download', 'data.csv')[0].click();
为什么不用正则全局替换 <.*?>
看起来最省事的方法是导出前对所有单元格 innerHTML 执行 .replace(/<[^>]*>/g, ''),但实际非常危险。
因为真实业务中常有字段本身含小于号、大于号或尖括号语义(比如日志内容、代码片段、数学表达式),正则无差别剔除会误伤数据。
- 例如
d.content = 'x < y and y > 5',被删成'x and y ' - 又比如 JSON 字符串字段:
'{"a":"<b>test</b>"}',正则会破坏结构 - 更隐蔽的是 XSS 防御场景:有些字段本就是用户输入的 HTML,你得保留原意,只是导出时需转义而非删除
所以清洗必须基于语义:哪列是状态标签、哪列是操作按钮、哪列是富文本展示 —— 分列处理,而不是一刀切。
真正难的从来不是“怎么删标签”,而是“哪些该删、哪些该转义、哪些该保留原样”。这得贴着你的数据模型来定,没法通用。



















