Vue2项目中实现将页面中指定DOM导出为PDF格式。自定义隐藏指定DOM中不想打印出来的内容。
首先是需要用到的依赖:html2canvas、jspdf
首先将导出功能封装成一个按钮组件(当然如果使用频率不高就没必要,反而更方便隐藏不想打印的内容)
<template>
<!-- 导出分析报告 -->
<el-button :loading="exporting" :disabled="disabled" @click="exportPic">导出分析报告</el-button>
</template>
<script>
import html2canvas from 'html2canvas';
import JsPDF from 'jspdf'
export default {
name: 'exportPicButton',
props: {
operationClass: String,
disabled: Boolean
},
data() {
return {
exporting: false
}
},
methods: {
/**
* 导出分析报告
*/
exportPic() {
if (!this.operationClass) return;
// 防御避免导出时重复点击,导完后才允许点击
if (this.exporting) return;
// 显示导出中
this.exporting = true;
this.$emit('before-export');
// 截图
this.$nextTick(() => {
setTimeout(() => {
const dom = document.querySelector(`.${this.operationClass}`);
html2canvas(dom, {
height: dom.scrollHeight,
windowHeight: dom.scrollHeight,
// 解决导出卡顿问题
ignoreElements: e => {
if (
e.contains(dom) ||
dom.contains(e) ||
e.tagName === 'STYLE' ||
e.tagName === 'LINK' ||
e.tagName === 'HEAD' ||
e.getAttribute('data-html2canvas') != null // header里面的样式不能筛掉
) {
return false;
}
return true;
}
}).then(canvas => {
let contentWidth = canvas.width;
let contentHeight = canvas.height;
let pageHeight = contentWidth / 592.28 * 841.89;
let leftHeight = contentHeight;
let position = 0;
let imgHeight = 592.28 / contentWidth * contentHeight;
let pageData = canvas.toDataURL('image/jpeg', 1.0);
let PDF = new JsPDF('', 'pt', 'a4');
// 边距
const margin = 20;
// 调整图片宽度和高度以适应页面并保持比例
let imgWidth = 595.28 - 2 * margin;
imgHeight = imgWidth / 595.28 * imgHeight;
if (leftHeight < pageHeight) {
PDF.addImage(pageData, 'JPEG', margin, margin, imgWidth, imgHeight);
} else {
while (leftHeight > 0) {
PDF.addImage(pageData, 'JPEG', margin, margin + position, imgWidth, imgHeight);
leftHeight -= pageHeight;
position -= 841.89;
if (leftHeight > 0) {
PDF.addPage();
}
}
}
// 当前时间
const now = new Date();
const nowStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
PDF.save(`分析报告${nowStr}.pdf`)
// 关闭导出中
this.exporting = false;
}).catch((err) => {
// 显示按钮
this.exporting = false;
// todo 处理异常
console.log(err);
}).finally(() => {
this.$emit('after-export');
});
}, 500)
});
}
}
}
</script>
javascript
组件只有一个按钮内容,props中接收的operationClass(需要打印DOM的class名称)、disabled(打印/导出按钮是否可用),emit事件有before-export(导出前要做的事情,如影响导出必须为同步)、after-export(导出后要做的事情)
使用方式:
<template>
<div class="main" v-loading="pageLoading">
<div class="page-title">
<export-pic-button
v-show="showHidden"
size="small"
:disabled="!canExportAnalysisReport"
operation-class="content"
@before-export="() =>{
showHidden = false;
pageLoading = true;
}"
@after-export="() => {
showHidden = true;
pageLoading = false;
}"
></export-pic-button>
</div>
<div class="content">
要打印的内容
<div class="hidden" v-show="showHidden">打印时不想展示的内容</div>
</div>
</div>
</template>
<script>
import ExportPicButton from "@/pages/index/views/zkgl/analyse/components/ExportPicButton.vue";
export default {
name: 'export-pic',
components: {ExportPicButton},
data() {
return {
// 是否可导出
canExportAnalysisReport: true,
// 按钮是否显示
showHidden: true,
// 页面加载中
pageLoading: false,
};
},
};
</script>
js
导出PDF为分析报告2024-08-06.pdf