核心实现思路

网页本身无法直接操作用户的本地文件系统(出于安全考虑),所以导出功能的实现通常分为两步:

  1. 前端生成 Excel 文件内容:在浏览器中,将 HTML 表格的数据转换成 Excel 能识别的格式(最常用的是 XML 格式,即 .xlsx 文件的本质)。
  2. 触发下载:生成一个包含该内容的虚拟文件链接,然后模拟用户点击这个链接,让浏览器下载文件。

主流方案推荐

以下是目前最流行、最好用的几种方案,按推荐度和易用性排序。

SheetJS (xlsx / js-xlsx) - 功能最强大,兼容性最好

这是目前功能最全面、社区最活跃的解决方案,几乎是专业级项目的首选。

  • 特点

    • 全能:不仅能导出,还能导入 Excel 文件,进行数据读写、修改等复杂操作。
    • 格式丰富:支持导出为 .xlsx (Excel 2007+), .xls (Excel 97-2003), .csv, .txt 等多种格式。
    • 样式支持:可以设置单元格的字体、颜色、边框、合并单元格、冻结窗格等复杂样式。
    • 纯前端:所有处理都在浏览器端完成,无需服务器。
    • 体积稍大:功能强大意味着库文件相对较大(约 500KB+,但可通过 Tree Shaking 减小)。
  • 使用场景

    • 需要处理复杂 Excel 样式和格式的项目。
    • 需要导入 Excel 文件并进行数据解析的项目。
    • 对数据准确性要求极高的后台管理系统。
  • 简单示例

    1. 安装:

      npm install xlsx
      # 或
      yarn add xlsx
    2. HTML:

      <table id="my-table">
        <thead>
          <tr>
            <th>姓名</th>
            <th>年龄</th>
            <th>城市</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>张三</td>
            <td>25</td>
            <td>北京</td>
          </tr>
          <tr>
            <td>李四</td>
            <td>30</td>
            <td>上海</td>
          </tr>
        </tbody>
      </table>
      <button id="export-btn">导出 Excel</button>
    3. JavaScript:

      document.getElementById('export-btn').addEventListener('click', function() {
        // 1. 获取表格元素
        const table = document.getElementById('my-table');
        // 2. 使用 SheetJS 的 table_to_book 方法将表格转换为工作簿对象
        const workbook = XLSX.utils.table_to_book(table);
        // 3. 生成 Excel 文件的二进制流
        const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
        // 4. 创建 Blob 对象
        const blob = new Blob([excelBuffer], { type: 'application/octet-stream' });
        // 5. 触发下载
        const url = window.URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = '数据表.xlsx'; // 设置文件名
        link.click();
        // 6. 释放 URL 对象
        window.URL.revokeObjectURL(url);
      });

FileSaver.js + 自定义逻辑 - 简单直接

这是一个更轻量级的方案,核心是解决“如何触发下载”的问题,你需要自己将表格数据转换成 CSV 或纯文本格式。

  • 特点

    • 极轻量:FileSaver.js 本身非常小,只负责保存文件。
    • 简单:对于简单的 CSV 导出,几行代码就能搞定。
    • 依赖手动转换:你需要自己编写逻辑将表格数据拼接成 CSV 字符串。
  • 使用场景

    • 只需要导出为简单的 CSV 文件。
    • 对样式没有要求,只需要纯数据。
    • 项目追求极致的轻量化。
  • 简单示例

    1. 引入:

      <script src="https://cdn.jsdelivr.net/npm/file-saver@2.0.5/dist/FileSaver.min.js"></script>
    2. JavaScript:

      document.getElementById('export-btn').addEventListener('click', function() {
        const table = document.getElementById('my-table');
        let csv = [];
        // 获取所有行
        const rows = table.querySelectorAll('tr');
        // 遍历每一行
        for (let i = 0; i < rows.length; i++) {
          const row = [], cols = rows[i].querySelectorAll('td, th');
          // 遍历每个单元格
          for (let j = 0; j < cols.length; j++) {
            // 去除单元格内容中的逗号和换行符,避免格式错乱
            row.push('"' + cols[j].innerText.replace(/"/g, '""') + '"');
          }
          csv.push(row.join(','));
        }
        // 将数组转换为 CSV 字符串
        const csvStr = csv.join('\n');
        // 创建 Blob 并使用 FileSaver 保存
        const blob = new Blob([csvStr], { type: 'text/csv;charset=utf-8;' });
        saveAs(blob, '数据表.csv');
      });

使用现成的 UI 组件库 - 开箱即用

如果你已经在使用像 Element UI, Ant Design Vue, Vuetify 这样的 UI 框架,它们通常内置了表格组件,并且直接提供了导出功能,这是最省事的方式。

  • 特点

    • 集成度高:与框架无缝集成,样式统一。
    • 功能完善:通常支持自定义导出列、文件名等。
    • 依赖框架:你必须使用该 UI 框架。
  • 使用场景

    • 项目已经基于某个 UI 框架开发。
    • 追求开发效率,不想引入额外的第三方库。
  • 示例 (以 Element Plus 为例):

    <template>
      <el-table :data="tableData" style="width: 100%">
        <el-table-column prop="name" label="姓名" />
        <el-table-column prop="age" label="年龄" />
        <el-table-column prop="city" label="城市" />
      </el-table>
      <!-- 使用内置的导出按钮 -->
      <el-button type="primary" @click="exportExcel">导出 Excel</el-button>
    </template>
    <script>
    import { ref } from 'vue';
    import * as XLSX from 'xlsx'; // Element Plus 的导出功能通常依赖 SheetJS
    export default {
      setup() {
        const tableData = ref([
          { name: '张三', age: 25, city: '北京' },
          { name: '李四', age: 30, city: '上海' },
        ]);
        const exportExcel = () => {
          // 1. 准备数据
          const header = ['姓名', '年龄', '城市'];
          const data = tableData.value.map(item => [item.name, item.age, item.city]);
          // 2. 创建工作簿和工作表
          const ws = XLSX.utils.aoa_to_sheet([header, ...data]);
          const wb = XLSX.utils.book_new();
          XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
          // 3. 导出
          XLSX.writeFile(wb, '数据表.xlsx');
        };
        return {
          tableData,
          exportExcel,
        };
      },
    };
    </script>

方案对比与选择建议

特性/方案 SheetJS (xlsx) FileSaver.js + 自定义 UI 框架内置
功能强度 ⭐⭐⭐⭐⭐ (全能) ⭐ (仅数据) ⭐⭐⭐ (依赖框架)
易用性 ⭐⭐⭐ (需学习 API) ⭐⭐⭐⭐ (简单逻辑) ⭐⭐⭐⭐⭐ (开箱即用)
样式支持 ⭐⭐⭐⭐⭐ (丰富) ❌ (无) ⭐⭐⭐ (有限)
导入功能 ✅ (支持) ❌ (不支持) ❌ (通常不支持)
库体积 较大 (约 500KB+) 极小 (约 10KB) 0 (已包含在框架中)
推荐场景 专业项目,需要复杂功能 快速实现,简单数据导出 已使用 UI 框架的项目

如何选择?

  • 如果你的需求很简单,只是想把一个网页表格的数据快速导出成 CSV,用 FileSaver.js + 自定义逻辑 足够,代码量少。
  • 如果你的项目已经使用了 UI 框架,直接使用框架内置的导出功能,这是最省心、最高效的选择。
  • 对于绝大多数新项目,特别是需要生成专业、美观的 Excel 报表时,强烈推荐 SheetJS,它功能强大,文档完善,是事实上的行业标准,虽然体积稍大,但现代浏览器和打包工具都能很好地处理它。

额外注意事项

  1. 跨域问题:如果你的表格数据是通过 AJAX 从其他域名的 API 获取的,请确保服务器返回了正确的 CORS (跨域资源共享) 头,否则前端脚本无法读取数据。
  2. 大数据量性能:对于包含成千上万行数据的表格,前端生成和下载大文件可能会造成页面卡顿甚至崩溃,如果数据量非常大,建议采用后端生成 Excel 并提供下载链接的方案,将压力从浏览器转移到服务器上。