Vue-cli 中的打印功能(window.print)

本文介绍了如何在Vue-cli项目中实现打印功能,利用window.print()方法将网页保存为PDF并进行打印。详细讲解了print.js的封装、使用方法以及打印参数设置,包括页面样式、横竖屏模式和比例调整。同时提到了Vue组件中表单数据的处理,以及如何实现分页打印的技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Vue-cli 中的打印功能(window.print)

print.js 的封装

// print.js
export default {
  initIframe(printOption) {
    let printIframe = document.getElementById('easyPrintIframe');
    if (!printIframe) {
      printIframe = document.createElement('iframe');
      printIframe.id = 'easyPrintIframe';
      printIframe.style.position = 'fixed';
      printIframe.style.width = '0';
      printIframe.style.height = '0';
      printIframe.style.top = '-100px';
      if (window.location.hostname !== document.domain && navigator.userAgent.match(/msie/i)) {
        printIframe.src =
          'javascript:document.write("<head><script>document.domain="' + document.domain + '";</script></head><body></body>")';
      }
      document.body.appendChild(printIframe);
      printIframe.onload = () => {
        this.getStyle(printOption);
      };
    }else{
      printIframe.contentDocument.body.innerHTML = '';
      printIframe.contentDocument.head.innerHTML = '';
      this.getStyle(printOption);
    }
  },
  setValues () {
    const inputs = document.querySelectorAll('input');
    const textareas = document.querySelectorAll('textarea');
    const selects = document.querySelectorAll('select');
    for(let i = 0; i < inputs.length; i++) {
      if (inputs[i].type === "checkbox" || inputs[i].type === "radio") {
        if (inputs[i].checked === true) {
          inputs[i].setAttribute('checked', "checked")
        } else {
          inputs[i].removeAttribute('checked');
        }
      } else if (inputs[i].type === "text") {
        inputs[i].setAttribute('value', inputs[i].value)
      }
    }

    for(let i = 0; i < textareas.length; i++) {
      textareas[i].setAttribute('value', textareas[i].value);
    }

    for(let i = 0; i < selects.length; i++) {
      if (selects[i].type === 'select-one') {
        let child = selects[i].children;
        for (let j in child) {
          if (child[j].tagName === 'OPTION') {
            if (child[j].selected === true) {
              child[j].setAttribute('selected', "selected")
            } else {
              child[j].removeAttribute('selected')
            }
          }
        }
      }
    }
  },
  getStyle(printOption) {
    const printIframe = document.getElementById('easyPrintIframe');
    let styleList = '',
        styleTagList = document.querySelectorAll('style');
    for (let i = 0; i < styleTagList.length; i++) {
      styleList += styleTagList[i].outerHTML;
    }
    printIframe.contentDocument.head.innerHTML = styleList;

    let linkTagList = document.querySelectorAll('link');
    for (let i = 0; i < linkTagList.length; i++) {
      let link = document.createElement('link');
      link.setAttribute('rel', 'stylesheet');
      if(styles[i].type) link.setAttribute('type', styles[i].type);
      else link.setAttribute('type', 'text/css');
      link.setAttribute('href', styles[i].href);
      link.setAttribute('media','all');
      printIframe.contentDocument.head.appendChild(link);
    }

    let printOptionStyle = document.createElement('style');
    printOptionStyle.innerHTML = '@media print {' + printOption + '}';
    printIframe.contentDocument.head.appendChild(printOptionStyle);
  },
  print(context, printOption = '') {
    this.initIframe(printOption);
    const $iframe = document.getElementById("easyPrintIframe");
    $iframe.contentDocument.body.innerHTML = context.$el.outerHTML;
    context.$nextTick(() => {
      setTimeout(() => {
        $iframe.contentWindow.focus();
        try {
          if (!$iframe.contentWindow.document.execCommand('print', false, null)) {
            $iframe.contentWindow.print();
            WebBrowser.ExecWB(7, 1);
          }
        } catch (e) {
          $iframe.contentWindow.print();
          WebBrowser.ExecWB(7, 1 );
        }
        $iframe.contentWindow.close();
      }, 100);
    });
  }
}

使用

import Println from 'print.js'
// hello.vue
...
created() {
  Println.print(this, print(this, `
    @page { size: portrait; color: #f00}
    .hello {transform: scale(1.0);}
  `);
}
...

说明

打印其实并不是连打印机打印,而是将网页保存成 PDF, 然后用电脑连接打印机打印。
可以将 print.js 导入某个组件使用,也可以绑定给 Vue 原型。
调用打印时传的参数,第一个是要打印的 Vue 组件,第二是打印时的样式设置,至于还可以做哪些设置,可以去官网看(页眉,页脚,纸张大小等都可以设置)。
打印的步骤
  • 创建 iframe 标签
  • 获取要打印的组件中的样式,添加给 iframe
  • 打印
调用示例里传的打印样式设置的参数中,size 可以确定预览的横竖屏模式,scale 可以设置打印的比例。
setValues 函数中之所以要对表单项重新赋值是因为 Vue 中的表单项的值是通过 v-model 绑定的,直接打印时读不到这个值,需要通过 JS 读取值并重新设置 value 属性。
有时候需要分页打印,分页打印要么就是内容太多自动分页,要是自己控制分页的话,需要将每页的内容单独放在独立的标签中,然后通过标签样式控制,让其打印时自动分页。
...
<style>
.page {
  page-break-after: always;
}
</style>
...
<div class="page">第一页</div>
<div class="page">第二页</div>
<div class="page">第三页</div>
...

扫码拉你进入前端技术交流群

在这里插入图片描述

Vue3中集成Ant Design(简称antd)并实现打印功能,通常需要借助一些库如vue-print-nb或者axios配合print.js完成。以下是基本步骤: 1. **安装依赖**: - 首先确保已安装Vue CLI,并创建一个新的项目。然后通过`npm install`或`yarn add`安装`@ant-design-vue/components`(antd的Vue组件库)和必要的打印库,比如`vue-print-nb`和`print-js`。 ```bash npm install @ant-design-vue/components print-js vue-print-nb # 或者 yarn add @ant-design-vue/components print-js vue-print-nb ``` 2. **引入组件**: 在你的Vue组件中,导入需要的打印相关的组件,例如`@ant-design-vue/button`用于生成打印按钮,`vue-print-nb`的打印组件等。 ```javascript import { Button } from '@ant-design-vue/components'; import Print from 'vue-print-nb'; ``` 3. **添加打印功能**: 在模板中,你可以创建一个按钮,当点击时触发打印。这里使用`vue-print-nb`的`print`函数,可以设置打印选项,如页面范围、缩放比例等。 ```html <template> <div> <Button type="primary" @click="handlePrint">打印</Button> <Print :url="printUrl" :options="{type: 'html', page: 'auto'}"></Print> </div> </template> <script> export default { data() { return { printUrl: '', // 这里可以根据需要动态设置URL }; }, methods: { handlePrint() { this.printUrl = '当前视图的HTML'; // 如果你想打印当前页面,可以用window.document.body.innerHTML; // 使用print-js实例化并调用打印 new PrintJS({ printable: this.printUrl, type: 'html', // 可选值有'text'、'image'、'html' landscape: false, // 是否横版打印 }).print(); }, }, }; </script> ``` 4. **注意点**: - `printUrl`可以是当前页面的HTML内容,也可以是一个API接口地址,返回的数据需经过处理再作为打印内容。 - 考虑到性能和安全性,不建议直接将整个页面HTML传递给用户进行打印,而是提供需要的内容。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

锋利的二丫

如果对您有帮助,请博主喝杯奶茶

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值