vue2使用jspdf插件实现页面自定义块pdf下载方式

 更新时间:2026年04月23日 09:14:59   作者:前端探险家  
本文介绍了在Vue项目中实现PDF下载功能的案例,使用了jspdf和html2-canvas插件,实现了点击按钮弹出下载进度弹窗并显示四个模块下载进度,下载完成后关闭弹窗的功能,文中提供了使用的插件版本和相关代码,供读者参考

实现pdf下载的环境

项目需求案例背景,点击【pdf下载】按钮,弹出pdf下载弹窗,显示需要下载四个模块的下载进度,下载完成后,关闭弹窗即可!

  • 项目使用的是Vue2,版本为^2.5.10;
  • jspdf插件版本为^2.5.1
  • html2canvas插件版本为^1.4.1

安装jspdf插件

npm install jspdf@2.5.1
npm install html2canvas@1.4.1

在项目中使用

下面是在项目中的使用相关的代码包括引入,状态,以及相关函数,模版的代码就直接省略掉了;仅供大家参考;

import JsPDF from "jspdf";
import html2Canvas from "html2canvas";
 data(){
   return {
     pdfDownLoadStatus:false,
     pdfDownLoadSteps:[],
   }
 }

点击事件以及相关函数

//点击pdf下载按钮事件
 downPdf(){
	 //pdf下载状态开启
	 this.pdfDownLoadStatus = true;
	 //需要截屏的区域,用在渲染pdf下载弹窗进度里面的内容
	 //code为页面下载区域的id
	 this.pdfDownLoadSteps = [
        { code: "idxxx1", name: "xx基本信息", status: "wait" },
        { code: "idxxx2", name: 'xx列表', status: "wait" },
        { code: "idxxx3", name: 'xx效果', status: "wait" },
        { code: "idxxx4", name: 'xx意见', status: "wait" },
      ];
      //打开pdf下载进度弹框,这里就这个弹窗模版中代码就省略掉了
      this.$refs.pdfDownloadModal.open();
      //pdf下载相关函数
      this.getPdf('下载文件名称');
 },

 async getPdf(title){
      let PDF = new JsPDF({
        unit: 'pt',
        format: 'a4',
        orientation: 'p',
      });
      let A4_WIDTH = 595.28
      let A4_HEIGHT = 841.89
      //pdf添加内容y轴起始位置
      let position = 0
      //判断是否有下载内容
      if (this.pdfDownLoadSteps && this.pdfDownLoadSteps.length > 0) {
        //y:pdf截屏区域的下标
        for (let y = 0 ; y < this.pdfDownLoadSteps.length ; y++) {
          //折叠面板
          let item = this.pdfDownLoadSteps[y];
          //开始
          item.status = 'valid';
          //将折叠面板转为canvas元素添加到pdf实例
          await this.toCanvasPanel(PDF, position, document.querySelector("#" + item.code), A4_WIDTH, A4_HEIGHT).then((data)=>{
            position = data.pdfPosition;
            this.generatePdf(item, this.pdfDownLoadSteps, y, title, PDF);
          });
        }
      }
 },

 /**
 * 生成PDF
  * @param item 当前区域下载状态
  * @param pdfDownLoadSteps 截屏的区域名
  * @param y 当前区域下标
  * @param title 文件标题
  * @param PDF
  */
  generatePdf(item, pdfDownLoadSteps, y, title, PDF) {
      //完成
      item.status = 'success';
      //最后一个截屏区域
      if (y == this.pdfDownLoadSteps.length - 1) {
        PDF.save(title + '.pdf');
        //pdf下载状态取消
        this.pdfDownLoadStatus = false;
      }
  },

 /**
 * 将折叠面板转为canvas元素添加到pdf实例
  * @param PDF
  * @param position 添加内容的起始位置
  * @param dom
  * @param imgWidth 图片宽度
  * @param pdfHeight pdf页高
  * @returns {Promise<unknown>}
  */
  toCanvasPanel(PDF, position, dom, imgWidth, pdfHeight){
      var p = new Promise(function(resolve, reject){
        html2Canvas(dom, {
          background: "#FFF"
        }).then(function (canvas) {
          //获取canavs转化后的宽度
          let contentWidth = canvas.width;
          //获取canavs转化后的高度
          let contentHeight = canvas.height;
          //高度转化为PDF的高度
          let imgHeight = imgWidth / contentWidth * contentHeight;
          //转化成图片Data
          let pageData = canvas.toDataURL('image/jpeg', 1.0);
          //PDF当前页剩余高度
          let pageResidue = pdfHeight - position;
          //添加图片到pdf
          PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight);
          //图片高度>PDF当前页剩余高度
          if (imgHeight > pageResidue) {
            //图片剩余高度=图片高度-当前页剩余高度
            let imgResidue = imgHeight - pageResidue;
            while (imgResidue > 0) {
              //下一页起始位置=图片剩余高度-图片高度
              position = imgResidue - imgHeight;
              //图片剩余高度-PDF高度,获取图片剩余高度
              imgResidue -= pdfHeight;
              //增加分页
              PDF.addPage();
              PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight);
            }
          }
          //下次截屏的起始位置
          position = position.add(imgHeight);
          resolve({'state': false, 'pdfPosition': position});
        })
      });
      return p;
  },

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • vue设置一开始进入的页面教程

    vue设置一开始进入的页面教程

    今天小编就为大家分享一篇vue设置一开始进入的页面教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-10-10
  • vue.js父子组件传参的原理与实现方法

    vue.js父子组件传参的原理与实现方法

    这篇文章主要介绍了vue.js父子组件传参的原理与实现方法,结合实例形式分析了vue.js父子组件传参的基本原理、实现方法与相关操作注意事项,需要的朋友可以参考下
    2023-04-04
  • Nuxt.js踩坑总结分享

    Nuxt.js踩坑总结分享

    本篇文章主要介绍了Nuxt.js踩坑总结分享,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • Vue设置页面轮询实现方式

    Vue设置页面轮询实现方式

    这篇文章主要介绍了Vue设置页面轮询实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-11-11
  • 详解Vue 实例中的生命周期钩子

    详解Vue 实例中的生命周期钩子

    这篇文章主要介绍了详解Vue 实例中的生命周期钩子,在Vue的整个生命周期中,它提供了一些生命周期钩子,给了我们执行自定义逻辑的机会。
    2017-03-03
  • vue添加vue-awesome-swiper轮播组件方式

    vue添加vue-awesome-swiper轮播组件方式

    这篇文章主要介绍了vue添加vue-awesome-swiper轮播组件方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • 详解vue-router 2.0 常用基础知识点之router.push()

    详解vue-router 2.0 常用基础知识点之router.push()

    本篇文章主要介绍了vue-router 2.0 常用基础知识点之router.push(),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • vue 中 beforeRouteEnter 死循环的问题

    vue 中 beforeRouteEnter 死循环的问题

    这篇文章主要介绍了vue beforeRouteEnter 死循环的问题,在文章末尾给大家补充介绍了vue中beforeRouteEnter使用的误区,需要的朋友可以参考下
    2019-04-04
  • 详解win7 cmd执行vue不是内部命令的解决方法

    详解win7 cmd执行vue不是内部命令的解决方法

    这篇文章主要介绍了详解win7 cmd执行vue不是内部命令的解决方法的相关资料,这里提供了解决问题的详细步骤,具有一定的参考价值,需要的朋友可以参考下
    2017-07-07
  • vue自定义实例化modal弹窗功能的实现

    vue自定义实例化modal弹窗功能的实现

    这篇文章主要介绍了vue自定义实例化modal弹窗,Vue.extend 属于Vue的全局 api,在实际业务开发中我们很少使用,因为相比常用的 Vue.component写法使用 extend 步骤要更加繁琐一些,本文结合实例代码给大家介绍的非常详细,需要的朋友参考下
    2022-09-09

最新评论