因为浏览器不支持直接生成.xlsx文件,Blob是前端唯一能安全封装二进制数据并触发下载的机制;CSV会丢失样式、格式且易乱码,而SheetJS配合Blob可导出带样式的.xlsx文件。

导出 Excel 时为什么用 Blob 而不是直接拼接 CSV?
因为浏览器不支持直接生成 .xlsx 文件(二进制格式),而 Blob 是前端唯一能安全封装二进制数据并触发下载的机制。用 CSV 确实简单,但会丢失样式、多行文本、公式、数字格式(比如 00123 变成 123),且 Excel 打开时可能乱码或警告“文件格式与扩展名不匹配”。真要导出 .xlsx,必须用库生成二进制内容再转为 Blob。
用 SheetJS(xlsx.js)导出带样式的 Excel 表格
SheetJS 是目前最稳定的纯前端 Excel 处理库,支持读写 .xlsx,且能保留单元格格式、合并、字体等。它不依赖后端,所有逻辑在浏览器完成。
关键步骤:
- 引入
https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js(注意用 full 版,lite 版不支持写入) - 用
document.querySelector拿到<table>元素,传给XLSX.utils.table_to_sheet() - 调用
XLSX.write()生成二进制array或base64,再用new Blob()封装 - 用
URL.createObjectURL()创建临时链接,触发下载
示例代码片段:
立即学习“前端免费学习笔记(深入)”;
const table = document.getElementById('my-table');
const ws = XLSX.utils.table_to_sheet(table);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, '数据表');
const wbout = XLSX.write(wb, { type: 'array', bookType: 'xlsx' });
const blob = new Blob([wbout], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = '导出表格.xlsx';
a.click();
URL.revokeObjectURL(url);
导出时中文乱码、日期错位、数字被科学计数怎么办?
这是 table_to_sheet() 默认行为导致的:它会按 HTML 内容自动推断类型(如把 2024-01-01 当字符串,把 1234567890123 当数字),且不处理 contenteditable 或自定义属性中的格式信息。
解决方法:
- 对日期列,先用 JS 格式化为
YYYY-MM-DD字符串,并确保单元格内无空格或换行 - 对需要左对齐的数字(如工号
00123),在 HTML 中加data-t="s"属性:<td data-t="s">00123</td>,然后用XLSX.utils.table_to_sheet(table, { raw: false }) - 避免在
<td>里嵌套<div>或<span>;复杂结构建议先用 JS 构造 JSON 数据,再用XLSX.utils.json_to_sheet()
Blob 导出失败或点击无反应的常见原因
不是代码写错了,而是浏览器策略或 DOM 状态问题。
排查点:
-
table元素为空或未挂载到 DOM —— 确保执行导出前table已渲染,不要在useEffect或mounted阶段过早调用 -
URL.createObjectURL()后没调用URL.revokeObjectURL()—— 不 revoke 会导致内存泄漏,尤其在频繁导出场景下 - 在 iOS Safari 上,
a.click()在非用户手势(如 setTimeout 异步)中会被拦截 —— 必须保证导出函数由用户真实点击触发(比如绑定在<button onclick="exportExcel()">) - Chrome 117+ 对 Blob URL 下载增加了更严的 MIME 校验 ——
type必须严格匹配application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,少一个字符都不行
真正麻烦的从来不是“怎么生成 Excel”,而是“怎么让每个单元格按你想要的样子出现”。尤其是合并单元格、冻结首行、设置列宽这些,SheetJS 都得手动配置 ws['!cols'] 和 ws['!merges'],一不留神就导出失败或格式错乱。



















