年前一个需求扔了过来,需要把页面展示的文本、表格、echats图、等等,按照页面展示的样子导出到word中,还要纯前端玩,不能走后端返回。需求就是圣旨无奈的开始了各种百度+api的尝试。
一、首先尝试jquery+FileSaver+wordexport的方案
参考demo:wordExport 导出页面word文档格式 - 简书
按照demo操作,可以导出页面上的文字和表格,echarts图无法显示,样式还必须写在行内,否则无法生效。
二、 html-docx-js + raw-loader + raw-loader 方案
安装相关的组件
npm install --save html-docx-js 组装html结构
npm install --save file-saver 导出到word
npm install --save raw-loader 解决样式引入问题,
参考demo:html导出docx文件_100斤的狗的博客-CSDN博客_html-docx
引入需要的组件
import htmlDocx from 'html-docx-js/dist/html-docx';
import saveAs from 'file-saver';
import reportCss from "raw-loader!./toWord.css.txt";需要创建一个存放css的txt文件(文件中每个容器的class只能有一个,多个class测试时不支持)
实际操作完整代码如下:
<template>
<div class="creat-dom">
<div v-for="(item, index) in listDatas" :key="index">
<div
v-if="item.type == 0" >
{{ item.html }}
</div>
<!-- 表格 -->
<div v-if="item.type == 1" class="table-div">
<p class="headers">表头</p>
<table border="1" class="table-div">
<tr>
<th>表头</th>
<th>表头</th>
</tr>
<tr>
<td>内容</td>
<td>内容</td>
</tr>
</table>
</div>
<!-- echarts图 -->
<div v-if="item.type == 2 ">
<img :src="item.url" />
</div>
<!-- 图片 -->
<div v-if="item.type == 3">
<img :src="item.image" />
</div>
</div>
</div>
</template>
import htmlDocx from "html-docx-js/dist/html-docx";
import saveAs from "file-saver";
import reportCss from "raw-loader!./toWord.css.txt"; // 解决word中的样式
export default {
name: "webTextToWord",
props: {
domDatas: {
type: Array,
default: () => [],
},
},
data() {
return {
listDatas: [],
};
},
methods: {
/* 点击“导出”进行下载
*/
async toWordHandle() {
this.listDatas = JSON.parse(JSON.stringify(this.domDatas));
let flagment = document.getElementById("toWordRef").innerHTML;
var page = `<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>${reportCss}</style>
</head>
<body>
<div class="web-text-to-word">
${flagment}
</div>
</body>
</html>`;
var converted = htmlDocx.asBlob(page);
saveAs(converted, "test.docx");
this.$emit("downloadFinish");
},
},
导出时文字和表格能正常导出,把echarts图转为base64后仍然卡死,不能显示。
陷入沉思……
经提醒,发现导出时echarts图还没有渲染完成!翻阅echartsAPI,使用on来监听渲染情况。开始使用了render,可以导出图片到word中,但是echarts会被执行多次,换成finished后终于成功导出了带样式的word文档。
render和finished的区别可以参数:echarts图表渲染后执行某一个方法_weixin_33953249的博客-CSDN博客
this.$nextTick(() => {
this.chartDom = this.$refs.echarts;
this.myChart = this.$echarts.init(this.chartDom);
this.option && this.myChart.setOption(this.option);
this.myChart.on("finished", () => {
this.base64URL = this.myChart.getDataURL();
this.$emit("base64UrlFa", this.base64URL);
});
});
到此导出的需求终于完美实现了!