vue3 + xlsx 实现导出表格,动态获取表头和数据
针对第三方表格组件(如 vxe-table 或 el-table),通过其提供的 API 获取表头和数据,而不是直接操作 DOM。以下是针对 vxe-table 和 el-table 的通用导出函数封装:
npm install xlsx
1. 封装通用导出函数
import * as XLSX from 'xlsx'
/**
* 导出表格数据为 Excel 文件
* @param {Object} tableRef - 表格组件的 ref 引用
* @param {String} fileName - 导出文件名(默认:export.xlsx)
* @param {Object} options - 配置项(可选)
* @param {Array} options.headers - 自定义表头(可选)
* @param {Array} options.dataKeys - 自定义数据字段(可选)
*/
export const exportExcel = (tableRef, fileName = 'export.xlsx', options = {}) => {
// 获取表头和数据
let headers = []
let data = []
// 判断表格类型并提取数据
if (tableRef.$options.name === 'VxeTable') {
// vxe-table 处理逻辑
headers = tableRef.getColumns().map(col => col.title)
data = tableRef.getTableData().fullData
} else if (tableRef.$options.name === 'ElTable') {
// el-table 处理逻辑
headers = tableRef.columns.map(col => col.label)
data = tableRef.data
} else {
throw new Error('不支持的表格组件类型')
}
// 自定义表头和数据字段(如果传入 options)
if (options.headers) {
headers = options.headers
}
if (options.dataKeys) {
data = data.map(item => {
return options.dataKeys.reduce((obj, key) => {
obj[key] = item[key]
return obj
}, {})
})
}
// 构建工作表数据
const worksheetData = [
headers, // 表头行
...data.map(item =>
headers.map(header => {
// 自动匹配数据字段(假设表头与数据字段一一对应)
const key = Object.keys(item).find(k =>
k.toLowerCase() === header.toLowerCase()
)
return key ? item[key] : ''
})
)
]
// 创建 workbook
const workbook = XLSX.utils.book_new()
const worksheet = XLSX.utils.aoa_to_sheet(worksheetData)
// 添加样式
worksheet['!cols'] = headers.map(() => ({ wch: 20 })) // 列宽
// 组合并导出
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1')
XLSX.writeFile(workbook, fileName)
}
2. 在组件中使用
vxe-table 示例
<template>
<vxe-table ref="tableRef" :data="tableData">
<vxe-column field="name" title="姓名" />
<vxe-column field="age" title="年龄" />
<vxe-column field="city" title="城市" />
</vxe-table>
<button @click="exportData">导出Excel</button>
</template>
<script setup>
import { ref } from 'vue'
import { exportExcel } from '@/utils/exportExcel'
const tableRef = ref(null)
const tableData = ref([
{ name: '张三', age: 25, city: '北京' },
{ name: '李四', age: 30, city: '上海' }
])
const exportData = () => {
exportExcel(tableRef.value, '用户数据.xlsx')
}
</script>
el-table 示例
<template>
<el-table ref="tableRef" :data="tableData">
<el-table-column prop="name" label="姓名" />
<el-table-column prop="age" label="年龄" />
<el-table-column prop="city" label="城市" />
</el-table>
<button @click="exportData">导出Excel</button>
</template>
<script setup>
import { ref } from 'vue'
import { exportExcel } from '@/utils/exportExcel'
const tableRef = ref(null)
const tableData = ref([
{ name: '张三', age: 25, city: '北京' },
{ name: '李四', age: 30, city: '上海' }
])
const exportData = () => {
exportExcel(tableRef.value, '用户数据.xlsx')
}
</script>
3. 高级用法
自定义表头和数据字段
const exportData = () => {
exportExcel(tableRef.value, '用户数据.xlsx', {
headers: ['姓名', '城市'], // 自定义表头
dataKeys: ['name', 'city'] // 自定义数据字段
})
}
导出特定数据
const exportData = () => {
const filteredData = tableData.value.filter(item => item.age > 25)
exportExcel(tableRef.value, '用户数据.xlsx', {
data: filteredData // 导出过滤后的数据
})
}
4. 注意事项
-
表头与数据字段匹配:
默认情况下,表头(title 或 label)与数据字段(field 或 prop)需要一一对应。 如果表头与字段不一致,可以通过 options.headers 和 options.dataKeys 自定义。
-
大数据量导出:
如果数据量较大,建议分批次导出或添加加载提示。
-
样式优化:
可以通过 worksheet['!cols'] 调整列宽,或使用 XLSX.utils.sheet_add_json 添加样式。