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

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>
...

猜你喜欢

转载自blog.csdn.net/FlowGuanEr/article/details/105514875