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)
相关推荐
定栓4 分钟前
Webpack迁到Vite第一节:模块系统迁移:require → import
运维·前端·webpack
小熊在忙fpga13 分钟前
N32G430芯片的flash表示
前端·javascript·html
Data analyse45619 分钟前
App埋点版本兼容的字段迁移校验
大数据·运维·服务器·前端·数据库·数据分析
todoitbo25 分钟前
本来只想给内网开个口子,Natapp 却多给了一道防护
前端·javascript·vue.js·内网穿透·网络防护·natapp
会灭火的程序员30 分钟前
SuperMap AgentX Server智能体接入WEB应用技术文档
前端·supermap·agentx·agentx server
CRMEB35 分钟前
商品 SKU 设计,从简单规格到多规格踩过什么
java·前端·数据库·开源
Chloe.Zz36 分钟前
一篇入门Agent
开发语言·前端·javascript
java1234_小锋1 小时前
【技术专题】HTML5 网页技术 - HTML5 表格标签
前端·html·html5
雪芽蓝域zzs1 小时前
JS 项目转 TS 项目(Vue3 + 若依这类后台项目)完整改造清单
前端·vue.js