Vue頁(yè)面生成PDF的最佳方法推薦
前言
最近項(xiàng)目有個(gè)需求,將系統(tǒng)統(tǒng)計(jì)的數(shù)據(jù)生成分析報(bào)告,然后可以導(dǎo)出成PDF。
這種方法可以有兩種,一種是直接調(diào)用打印,用戶通過(guò)瀏覽器提供的打印頁(yè)面手動(dòng)選擇導(dǎo)出PDF。當(dāng)然這種方式兼容性差,且體驗(yàn)不好,顯然不是我們想要的效果。
那么第二種方法的實(shí)現(xiàn)思路是什么呢?
首先生成報(bào)告頁(yè)面,也就是常規(guī)頁(yè)面;
然后將頁(yè)面轉(zhuǎn)換成圖片( 用到的組件 html2canvas );
最后將圖片導(dǎo)出成PDF( 用到的組件 jspdf )。
安裝依賴
npm install --save html2canvas // 頁(yè)面轉(zhuǎn)圖片 npm install jspdf --save // 圖片轉(zhuǎn)pdf
頁(yè)面轉(zhuǎn)圖片
新建一個(gè) index.vue 頁(yè)面:
<template>
<div ref="pdf">
這是待轉(zhuǎn)換的頁(yè)面,點(diǎn)擊
<button @click="handleExport">導(dǎo)出</button> 按鈕,完成導(dǎo)出操作。
</div>
</template>
<script>
import {downloadPDF} from "@/util/pdf.js" //工具方法,導(dǎo)出操作
export default {
name: "pdf",
data() {
return {};
},
methods: {
handleExport(){
downloadPDF(this.$refs.pdf)
}
}
};
</script>
頁(yè)面很簡(jiǎn)單,一段話加上一個(gè)導(dǎo)出按鈕。整個(gè)頁(yè)面被設(shè)置別名 (ref=“pdf”),導(dǎo)出的時(shí)候通過(guò)別名導(dǎo)出整個(gè)頁(yè)面。
按鈕點(diǎn)擊事件中調(diào)用了一個(gè)工具方法 downloadPDF(),來(lái)自于工具類 pdf.js:
import html2canvas from "html2canvas";
export const downloadPDF = page => {
html2canvas(page).then(function(canvas) {
page.appendChild(canvas);
});
};
也很簡(jiǎn)單,首先引入了 html2canvas,定義downloadPDF方法,接受一個(gè)參數(shù)就是要導(dǎo)出的內(nèi)容,可以使用id獲取,也可以使用 ref 。
運(yùn)行結(jié)果:

當(dāng)我們點(diǎn)擊導(dǎo)出按鈕后,在現(xiàn)有的頁(yè)面增加了一行相同的內(nèi)容。通過(guò)元素檢查器可以看到增加的這行內(nèi)容實(shí)際是一個(gè) canvas 圖像,里面的按鈕已經(jīng)不可以操作了。
這樣,頁(yè)面轉(zhuǎn)換圖片的過(guò)程就完成了。
圖片轉(zhuǎn)PDF
首先給index.vue改造一下,為了讓我們導(dǎo)出的pdf好看一點(diǎn),使用el-table做個(gè)表格,其它的導(dǎo)出邏輯不變:
<template>
<div ref="pdf">
<el-table
:data="tableData"
style="width: 700px">
<el-table-column
prop="date"
label="時(shí)間"
width="180">
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="address"
label="對(duì)我說(shuō)">
</el-table-column>
</el-table>
<button @click="handleExport">導(dǎo)出</button>
</div>
</template>
<script>
import {downloadPDF} from "@/util/pdf.js" //工具方法,導(dǎo)出操作
export default {
name: "pdf",
data() {
return {
tableData: [{
date: '昨天',
name: '劉德華',
address: '你好帥'
}, {
date: '今天',
name: '郭富城',
address: '你最帥'
}, {
date: '明天',
name: '張學(xué)友',
address: '你賊帥'
}, {
date: '每天',
name: '黎明',
address: '我沒(méi)你帥'
}]
};
},
methods: {
handleExport(){
downloadPDF(this.$refs.pdf)
}
}
};
</script>
效果圖:

然后改造一下pdf.js,增加上pdf轉(zhuǎn)換邏輯
import html2canvas from "html2canvas";
import jsPDF from "jspdf";
export const downloadPDF = page => {
html2canvas(page).then(function(canvas) {
canvas2PDF(canvas);
});
};
const canvas2PDF = canvas => {
let contentWidth = canvas.width;
let contentHeight = canvas.height;
let imgHeight = contentHeight;
let imgWidth = contentWidth;
// 第一個(gè)參數(shù): l:橫向 p:縱向
// 第二個(gè)參數(shù):測(cè)量單位("pt","mm", "cm", "m", "in" or "px")
let pdf = new jsPDF("l", "pt");
pdf.addImage(
canvas.toDataURL("image/jpeg", 1.0),
"JPEG",
0,
0,
imgWidth,
imgHeight
);
pdf.save("導(dǎo)出.pdf");
};
canvas2PDF 方法中創(chuàng)建了jsPDF的實(shí)例,然后添加上一步生成的圖片,最后保存導(dǎo)出pdf文件。
導(dǎo)出的文件效果:

A4打印適配
因?yàn)椴糠中枨笥行枰傻捻?yè)面使用A4紙打印,那么pdf生成時(shí)的寬高尺寸就不能像上面一樣設(shè)定。需要按照A4紙的尺寸比例調(diào)整(其它打印需求同理,使用對(duì)應(yīng)紙張比例即可)
那么改造一下 pdf.js
import html2canvas from "html2canvas";
import jsPDF from "jspdf";
export const downloadPDF = page => {
html2canvas(page).then(function(canvas) {
canvas2PDF(canvas);
});
};
const canvas2PDF = canvas => {
let contentWidth = canvas.width;
let contentHeight = canvas.height;
//a4紙的尺寸[595.28,841.89],html頁(yè)面生成的canvas在pdf中圖片的寬高
let imgWidth = 595.28;
let imgHeight = 592.28/contentWidth * contentHeight;
// 第一個(gè)參數(shù): l:橫向 p:縱向
// 第二個(gè)參數(shù):測(cè)量單位("pt","mm", "cm", "m", "in" or "px")
let pdf = new jsPDF("p", "pt");
pdf.addImage(
canvas.toDataURL("image/jpeg", 1.0),
"JPEG",
0,
0,
imgWidth,
imgHeight
);
pdf.save("導(dǎo)出.pdf");
};
這里面將 imgWidth 和 imgHeight 按照A4紙比例調(diào)整后,導(dǎo)出的pdf就可以正常比例打印了。
總結(jié)
到此這篇關(guān)于Vue頁(yè)面生成PDF的文章就介紹到這了,更多相關(guān)Vue頁(yè)面生成PDF內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue實(shí)現(xiàn)過(guò)渡動(dòng)畫Message消息提示組件示例詳解
這篇文章主要為大家介紹了vue實(shí)現(xiàn)過(guò)渡動(dòng)畫Message消息提示組件示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
詳解Vue3?SFC?和?TSX?方式調(diào)用子組件中的函數(shù)
在使用?.vue?定義的組件中,setup?中提供了?defineExpose()?方法,該方法可以將組件內(nèi)部的方法暴露給父組件,這篇文章主要介紹了Vue3?SFC?和?TSX?方式調(diào)用子組件中的函數(shù),需要的朋友可以參考下2022-10-10
Vue實(shí)例初始化為渲染函數(shù)設(shè)置檢查源碼剖析
這篇文章主要為大家介紹了Vue實(shí)例初始化為渲染函數(shù)設(shè)置檢查源碼剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
如何使用vue-pdf-embed實(shí)現(xiàn)PDF在線預(yù)覽
vue-pdf-embed是一個(gè)基于Vue.js的插件,專門用于在Vue應(yīng)用中嵌入和展示PDF文件,本文將使用vue-pdf-embed實(shí)現(xiàn)PDF在線預(yù)覽功能,有需要的小伙伴可以參考一下2025-03-03

