在 Vue 中实现点击按钮将后端响应的数据导出为 .xlsx
文件,可以使用 axios
进行数据请求,并结合 xlsx
和 file-saver
库完成文件的生成和下载。
以下是完整实现步骤:
1. 安装依赖库
运行以下命令安装所需的库:
npm install xlsx file-saver axios
2. 创建导出功能
组件代码示例
<template>
<div>
<button @click="exportExcel">导出数据为 Excel 文件</button>
</div>
</template>
<script>
import axios from "axios";
import * as XLSX from "xlsx";
import { saveAs } from "file-saver";
export default {
name: "ExportExcel",
methods: {
async exportExcel() {
try {
// 发送请求获取后端数据
const response = await axios.get("/api/v1/data-to-export", {
responseType: "json", // 确保返回的数据是 JSON 格式
});
// 假设后端返回的数据结构如下:
// response.data = [
// { name: "张三", age: 25, city: "杭州" },
// { name: "李四", age: 30, city: "上海" }
// ]
const data = response.data;
// 将数据转换为工作表格式
const worksheet = XLSX.utils.json_to_sheet(data);
// 创建工作簿并添加工作表
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, "活跃数据");
// 将工作簿转换为 Blob 对象
const excelBuffer = XLSX.write(workbook, {
bookType: "xlsx",
type: "array",
});
// 使用 file-saver 保存文件
const blob = new Blob([excelBuffer], {
type: "application/octet-stream",
});
saveAs(blob, "活跃数据.xlsx");
} catch (error) {
console.error("导出失败:", error);
}
},
},
};
</script>
<style scoped>
button {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
</style>
3. 后端响应接口
确保后端接口返回 JSON 格式的数据。例如:
Node.js 示例
app.get("/api/v1/data-to-export", (req, res) => {
const data = [
{ name: "张三", age: 25, city: "杭州" },
{ name: "李四", age: 30, city: "上海" },
];
res.json(data);
});
4. 功能解析
axios.get()
: 从后端获取数据。XLSX.utils.json_to_sheet()
: 将 JSON 数据转换为工作表。XLSX.utils.book_new()
和XLSX.utils.book_append_sheet()
: 创建工作簿并附加工作表。XLSX.write()
: 将工作簿转换为二进制数据。file-saver
的saveAs()
: 将 Blob 对象保存为文件并触发下载。
5. 效果
点击按钮时,将触发请求,获取后端数据,并生成并下载 .xlsx
文件。下载文件名为 活跃数据.xlsx
。
如果有更多需求(如文件格式或数据处理),可以在转换前对数据进行处理或增加其他逻辑。
6.项目中使用
<template>
<div>
<button style="margin-left: 95%;border: none;background-color: white;color: blue;" @click="refresh">刷新</button>
<el-divider></el-divider>
<div style="height: 160px;">
<el-row :gutter="20">
<el-col :span="4">
<div>
<el-statistic :value="data.newly_added_users_yesterday" title="昨日新增用户"></el-statistic>
</div>
</el-col>
<el-col :span="4">
<div>
<el-statistic :value="data.retain_the_next_day" title="次日留存"></el-statistic>
</div>
</el-col>
<el-col :span="4">
<div>
<el-statistic :value="data.day3_retention" title="3日留存"></el-statistic>
</div>
</el-col>
<el-col :span="4">
<div>
<el-statistic :value="data.day7_retention" title="7日留存"></el-statistic>
</div>
</el-col>
<el-col :span="4">
<div>
<el-statistic :value="data.day30_retention" title="30日留存"></el-statistic>
</div>
</el-col>
</el-row>
<hr style="width: 90%;margin-top: 2%;margin-bottom: 2%;">
<el-col :span="4">
<div>
<el-statistic :value="data.next_day_retention_rate" title="次日留存率"></el-statistic>
</div>
</el-col>
<el-col :span="4">
<div>
<el-statistic :value="data.day3_retention_rate" title="3日留存率"></el-statistic>
</div>
</el-col>
<el-col :span="4">
<div>
<el-statistic :value="data.Dday7_retention_rate" title="7日留存率"></el-statistic>
</div>
</el-col>
<el-col :span="4">
<div>
<el-statistic :value="data.day30_retention_rate" title="30日留存率"></el-statistic>
</div>
</el-col>
</div>
<el-divider></el-divider>
<div class="container">
<p style="margin-right: 2%;">{{ date }}</p>
<button style="border: none;background-color: white;color: blue;" @click="exportAsExc">导出</button>
</div>
<div style="border: 1px solid #e0e6f1;">
<DateSelection style="margin-top: 2%;" />
<div style="width: 100%;height: 400px;">
<BarChart :chart-data="barChartData" />
</div>
</div>
</div>
</template>
<script>
import BarChart from './components/BarChart.vue';
import DateSelection from './components/DateSelection.vue';
import { retentionDataBase } from '@/api/basic';
import { saveAs } from "file-saver";
import { mapGetters } from 'vuex';
export default {
components: {
BarChart,
DateSelection
},
computed: {
...mapGetters({
getGraphData: 'retentionOverview/getGraphData'
})
},
data() {
return {
data: {
day3_retention: 0,
day3_retention_rate: 0,
day7_retention: 0,
Dday7_retention_rate: 0,
day30_retention: 0,
day30_retention_rate: 0,
newly_added_users_yesterday: 0,
next_day_retention_rate: 0,
retain_the_next_day: 0
},
date: "",
like: true,
value1: 4154.564,
value2: 1314,
title: "总用户",
barChartData: {
xAxisData: ['12-13', '12-14', '12-15', '12-17', '12-18', '12-19', '12-20', '12-21', '12-22', '12-23', '12-24', '12-25'],
seriesData: [120, 200, 150, 80, 70, 110, 130, 123, 32, 12, 20, 60]
}
};
},
mounted() {
this.date = "更新时间:" + new Date().toLocaleString();
this.retentionDataBase();
},
methods: {
exportAsExc() {
import("xlsx").then((XLSX) => {
try {
if (!this.getGraphData || this.getGraphData.length === 0) {
this.$message.error("没有数据可导出");
return;
}
// 将数据转换为工作表格式
const worksheet = XLSX.utils.json_to_sheet(this.getGraphData);
// 创建工作簿并添加工作表
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, "活跃数据");
// 将工作簿转换为 Blob 对象
const excelBuffer = XLSX.write(workbook, {
bookType: "xlsx",
type: "array",
});
// 使用 file-saver 保存文件
const blob = new Blob([excelBuffer], {
type: "application/octet-stream",
});
saveAs(blob, "活跃数据.xlsx");
this.$message.success("数据导出成功!");
} catch (error) {
console.error("导出失败:", error);
this.$message.error("导出失败,请检查数据或重试!");
}
});
},
refresh() {
location.reload();
this.date = "更新时间:" + new Date().toLocaleString();
},
retentionDataBase() {
retentionDataBase().then(res => {
this.data = res;
console.log(res);
}).catch(error => {
console.error('Error fetching list data:', error);
});
},
}
};
</script>
<style lang="scss">
.like {
cursor: pointer;
font-size: 25px;
display: inline-block;
}
.container {
display: flex;
justify-content: flex-end;
}
</style>
来源链接:https://www.cnblogs.com/freps/p/18653325
没有回复内容