vue-实现打印功能

核心:

  • 直接调用window.print()
  • iframe 方式:iframe.contentWindow.print();

方式一:借助创建iframe元素,实现指定区域打印

handlePrint(){
        const iframeEL=document.querySelector('.target-el-iframe');
        if(iframeEL){
          iframeEL.remove();
        }
        //目标元素
        const info=document.querySelector('.print');
        //创建iframe
        const iframeEl= document.createElement('iframe');
        iframeEl.classList.add('target-el-iframe')
        iframeEl.setAttribute('style','width:90%')

        //添加到页面
        document.body.appendChild(iframeEl)
        const doc = iframeEl.contentWindow.document
        doc.write('<div class="print-iframe">' + info.innerHTML + '</div>')
        doc.write('<style>@page{size:auto;margin: 0.5cm 1cm 0cm 1cm;}</style>')
        doc.close()
        //引入第三方样式文件
        const link = doc.createElement('link');
        link.rel = 'stylesheet';
        link.href = '/static/print/print.less';

        doc.head.appendChild(link);
          //打印
          iframeEl.onload = () => {
          iframeEl.contentWindow.print()
        }

      },

思路:

1 判断是否有上次创建的iframe元素,若有,移除

2创建iframe元素,并给class类名,方便移除

3 设置打印页面内容

4 设置页面内容样式(因为有些样式会丢失,这里可以补上)

5 调用浏览器的打印方法实现打印

注意:

1 可能会出现样式丢失,可添加第三方样式文件

const doc = iframeEl.contentWindow.document;
const link = doc.createElement('link');
link.rel = 'stylesheet';
link.href = '/static/print/print.css';

doc.head.appendChild(link);

 示例:将样式文件放在public文件下的/static/print/print.css

@import url('./antd.css'); //引入antd样式文件

方式二:使用媒体查询

 直接使用window.print()

@media print {
  body * {
    visibility: hidden;
  }
//打印区
  #print-area, #print-area * {
    visibility: visible;
  }
  #print-area {
    position: absolute;
    left: 0;
    top: 0;
  }
}

思路:

1先将全部元素不可见

2 将打印区设置为可看见 

方法三:使用html2canvas结合iframe

好处:相较于方法一,不会出现样式丢失

缺陷:速度慢

 引入html2canvas库

import html2canvas from 'html2canvas'

handlePrint(){
        const iframeEL=document.querySelector('.print-iframe');
        if(iframeEL){
          iframeEL.remove();
        }
        // 获取要转换为图片的 DOM 元素
        const element = document.querySelector('.print');

        // 将 DOM 元素转换为 Canvas 对象
        html2canvas(element).then(canvas => {
          // 创建一个新的图片元素,并将 Canvas 对象作为背景图
          const img = new Image();
          img.src = canvas.toDataURL('image/png');
          img.style.width='100%'
          // 在 iframe 文档中添加图片元素
          const iframe = document.createElement('iframe');
          iframe.style.width='100%'
          iframe.classList.add('print-iframe')
          document.body.appendChild(iframe)
          const doc = iframe.contentWindow.document
          doc.body.appendChild(img);
          //避免图片没有加载完成就打印
          setTimeout(()=>{
            iframe.contentWindow.print();
          },100)

        })
      },

方法四 使用PrintJs插件

使用printjs时,遇到的坑:字体不生效,源码中字体统一是12pt,感觉很不理解

printView() {
      Printjs({
        printable: 'dayin', // 要打印内容的id
        type: 'html', // 可以打印html,img详细的可以在官方文档https://printjs.crabbly.com/中查询
        targetStyles: ['*'],
        // style: workOrderStyle(), // 打印的内容是没有css样式的,此处需要string类型的css样式
        // style: `@page{size:auto;margin: 0cm;}`, // 打印的内容是没有css样式的,此处需要string类型的css样式
        scanStyles: true,
        onLoadingEnd() {
          // showPrintNode.value = false
        }
      })

方法五

插件:vue-print-nb

安装:npm install vue-print-nb --save

引入

// 1. 全局挂载,在main.js添加
import Print from 'vue-print-nb'
Vue.use(Print)
// or
// 2. 自定义指令,在单业务页面添加
import print from 'vue-print-nb'
directives: {
  print
}

使用界面:

1 给打印的区域设置id值 

<a-button type="primary" v-print="print">打印</a-button>
export default {
  name: 'index',
  data(){
    let that = this
    return {
      print: {
        id: 'printContent',
        popTitle: '配置页眉标题', // 打印配置页上方的标题
        extraHead: '打印', // 最上方的头部文字,附加在head标签上的额外标签,使用逗号分割
        preview: true, // 是否启动预览模式,默认是false
        previewTitle: '预览的标题', // 打印预览的标题
        previewPrintBtnLabel: '预览结束,开始打印', // 打印预览的标题下方的按钮文本,点击可进入打印
        zIndex: 20002, // 预览窗口的z-index,默认是20002,最好比默认值更高
        previewBeforeOpenCallback () {
          console.log('正在加载预览窗口!');
          console.log(that.msg, this)
        }, // 预览窗口打开之前的callback
        previewOpenCallback () {
          console.log('已经加载完预览窗口,预览打开了!')
        }, // 预览窗口打开时的callback
        beforeOpenCallback () {
          console.log('开始打印之前!')
        }, // 开始打印之前的callback
        openCallback () {
          console.log('执行打印了!')
        }, // 调用打印时的callback
        closeCallback () {
          console.log('关闭了打印工具!')
        }, // 关闭打印的callback(无法区分确认or取消)
        clickMounted () {
          console.log('点击v-print绑定的按钮了!')
        },
        // url: 'http://localhost:8080/', // 打印指定的URL,确保同源策略相同
        // asyncUrl (reslove) {
        //   setTimeout(() => {
        //     reslove('http://localhost:8080/')
        //   }, 2000)
        // },
      }
    }
  },
}

 打印时发现,打印的效果不是想要的,或者表格边框线显示不全,使用媒体查询设置打印的样式

<style media="print" lang="scss">
// 修改页边距
@page {
  //size: auto;
  //margin: 3mm;
}
// 媒体查询, 打印时修改样式
@media print {
  .el-table{
    border: 3px solid #606060;
  }
  .el-table__header-wrapper {
    border-bottom: 3px solid #606060;
  }
  .el-table > .el-table__header-wrapper > .el-table__header > thead > tr > th{
    border-right: 3px solid #606060 !important;
  }
  .el-table > .el-table__body-wrapper > .el-table__body > tbody > .el-table__row > td{
    border-bottom: 3px solid #606060 !important;
    border-right: 3px solid #606060 !important;
  }
}
</style>

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值