vue实现打印PDF功能 - html2Pdf.js

踩坑预警

最近更新已经三年前的事情了,将近四百多个问题还未close(重复的问题也挺多的) 官网地址

安装操作

js 复制代码
npm install --save html2pdf.js 
or
npm install --save html2pdf.js -- force
or
cnpm install --save html2pdf.js 

实现直接下载保存PDF操作

可以通过html布局好了,直接打印下载

js 复制代码
import html2pdf from 'html2pdf.js';
let tableElement = document.querySelectorAll('table')
html2pdf().from(tableElement).save(filename);

踩坑历程

要求: 我这边是纯表格的打印操作,但是要求是分页的时候每个表格都是需要携带表头,表格内的图片需要展示

踩坑一: 网络图片无法展示

翻阅了源码开发者上别人提的Issues中发现,这玩意html2canvas处理的时候只能支持base64,虽然有人说可以配置 html2canvas: {scale: 2, useCORS: true},可以解决【但是我测试不行,开发者提议使用base64】

js 复制代码
let imageUrl = 'https://www.baidu.com/img/flexible/logo/pc/result.png'
let image = new Image();
//解决跨域问题
image.setAttribute('crossOrigin', 'Anonymous');
image.src = imageUrl
//image.onload为异步加载
let base64Datas = []
image.onload = () => {
    var canvas = document.createElement("canvas");
    canvas.width = image.width;
    canvas.height = image.height;
    var context = canvas.getContext('2d');
    context.drawImage(image, 0, 0, image.width, image.height);
    var quality = 0.8;
    //这里的dataurl就是base64类型
    var dataURL = canvas.toDataURL("image/jpeg", quality);//使用toDataUrl将图片转换成jpeg的格式,不要把图片压缩成png,因为压缩成png后base64的字符串可能比不转换前的长!
    //数组存放图片base64
    base64Datas.push(dataURL);
    //递归执行图片url转base64        
}

踩坑二: 表头没办法在分页后的自动携带上(printJS这个插件就相当不错,可太傲娇)

这个也是我搞了好久的地方,一开始在Issues中发现添加页码的方式想法去添加表头,如

js 复制代码
 html2pdf().from(tableElement).set(options).toPdf().get('pdf').then(function (pdf) {
    console.log(pdf)
    // paf.table({html: thead})
  }).save(filename);

,then做PDF的操作,打印PDF暴露出来的API方法中改哪个都油盐不进,一点变化都没有,放弃了,运用固定住表格里的数据高度固定,动态去插入表头进去每个数据中,实现现有表头功能

javascript 复制代码
 const clonedThead = tableElement.querySelector('thead').innerHTML;
  let tbodyList = tableElement.querySelectorAll('tbody');
  console.log(tbodyList)
  tbodyList.forEach((item,index) => {
    if( index % 5 === 0 && index > 0) {
      item.insertAdjacentHTML('afterbegin', '<div style="padding-top: 20px">'+clonedThead+'</div>');
    }
  })

踩坑三: 分页出现截断内容

  1. 配置options 解决分页问题:
javascript 复制代码
const options = {
    margin: 10,
    html2canvas: { 
      scale: 2 
    },
    jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait'},
    pagebreak: {  mode: ['avoid-all', 'css', 'legacy'] },
}
  1. 样式控制

page-break-inside: avoid 可以保留完整的页面

page-break-before: always 可以另起新的一页

从源码发现可以添加类 html2pdf__page-break 进行换页

css 复制代码
//对表格内容保持完整性
.td {
    min-width: 60px;
    text-align: center;
    word-wrap: break-word;
    word-break: break-all;
    border: 1px solid #000;
}

3. 浑身解数之后发现还是会保留一点第二页的数据在第一页中,这种情况有可能是html2canvas画的canvas和设置的A4纸的大小有关了

解决: 我这边运用了插入表头的时候增加个paddingTop的高度可以解决

printJS 打印使用

挺好用的,以上的要求基本能符合需求的开发要求,可惜开源博主在Issues中说我只专注打印开发,如果需要直接下载可以用别的插件很好支持,这边就专注于打印功能。 很显然有点满足不了我多表格区分下载的实现。他这个只支持于单个pdf导出打印预览,有实现过的小伙伴欢迎评论给出兼容的解决方案【【根据HTML可解决直接下载多个PDF】】

javascript 复制代码
// 与html2Pdf.js 区别在的是样式需要单独配置进插件中,无法识别html里的样式,
// 如果需要分页可以根据踩坑三中的样式控制操作,并且图片无需转成base64,
// 我要处理的图片出现跨域问题,在这个插件是不存在这个问题,直接自动处理网络图片
// 附上实现方案
setTimeout(() => {
    printJS({
      printable: 'print', // 要打印的id
      type: 'html',
      header: '',
      style: `@page{size:auto;margin: 0cm 1cm 0cm 1cm;}
      .store-img-stock {
        display:block;
        padding:20px;
        width: 260px;
        height: 260px;
      }
      .s-placeholder{ visibility: hidden; }
      @media print {
        body {
          -webkit-print-color-adjust: exact;
          -moz-print-color-adjust: exact;
          -ms-print-color-adjust: exact;
          print-color-adjust: exact;
        }
      }
      .hidden-border-bottom {
        border-bottom: none;
        border-top: none;
      }
      .thead-th {
        background-color: #333586 !important;
        color: #fff !important;
      }
      .empty-height {
        max-height: 50px;
      }
      .height-20 {
        height: 16px;
      }
      .store-table-a1 {
        margin-bottom: 20px;
        page-break-before: always;
      }
      .store-table-a1 td {
        min-width: 60px;
        text-align: center;
        word-wrap: break-word;
        word-break: break-all;
        border: 1px solid #000;
      }
      .store-table th {
        height: 35px;
        border: 1px solid #000;
      }
      .hidden-border {
        border: none !important;
      }
      ` // 去除页眉页脚
    })
  }, 500)
相关推荐
清秋12 分钟前
全网最全 ECMAScript 攻略( 更新至 ES2026)
前端·javascript·编程语言
Cao_Ron29 分钟前
用 SVG image symbol 画 ECharts graph 圆形节点
前端
hxy060134 分钟前
React-Call让你的React组件像异步函数一样调用
前端·react.js
Hilaku35 分钟前
为什么 AI 写前端时,总是优先选择 React,而不是 Vue?
前端·javascript·程序员
京东云开发者37 分钟前
GPT-5.6、ChatGPT Work 与 Codex 更新食用指南
前端
Cao_Ron1 小时前
用 ECharts graph 画出卡片式矩形节点
前端
skiyee1 小时前
换个底座的 Wot Starter 居然让 AI 更懂项目!
前端·ai编程
anyup1 小时前
这一套绝了!AI 大模型写故事,星云 SDK 驱动 3D 数字人实时演绎
前端·人工智能·aigc
耀耀切克闹灬1 小时前
短链跳转
前端
孟陬1 小时前
高质量全方位的 AI 工具 sse-stuntman — Mock SSE 接口
前端·node.js·openai