vue项目开发中如何实现打印功能???

2018, Oct 19    

方案1

  • 使用原生js的print 方法
var printhtml = window.getElementById(dom).innerHtml // 获取打印区域
var oldhtml = document.innerHtml // 保存原始内容
document.innerHtml = printhtml // 赋值打印
window.print()
document.innerHtml = oldhtml // 还原页面
window.location.reload() // 刷新解决页面无法点击

当然结果尝试后也很显然需要替换掉页面中的元素 显示打印元素这样有背我们的需求、且用户体验极差

方案2

  • 使用css3 中的@media print 来特殊标识打印设备 对齐设置相应样式 具体使用方法详见: @media
@media print {
    .not-print {
        opacity: 0
    }
}

方案3

  • 通过上面的例子我们可以发现window.print打印的是该页面的body内的innerHTML 所以为什么不适用iframe标签呢 iframe
<html>

<body>

<iframe src="/i/eg_landscape.jpg"></iframe>

<p>一些老的浏览器不支持 iframe。</p>
<p>如果得不到支持,iframe 是不可见的。</p>


</body>
</html>

iframe 属性

所以最终实现方案

<template>
  <div></div>
</template>
<script>
export default {
  name: 'swebPrint',
  props: ['data'],
  methods: {
    doPrint () {
      var iframe = document.createElement('iframe')
      var f = document.body.appendChild(iframe)
      var w = f.contentWindow || f.contentDocument
      w.document.write(this.data)
      f.contentWindow.focus()
      f.contentWindow.print()
      setTimeout(function () {
        document.body.removeChild(iframe)
      }, 100)
    }
  }
}
</script>

项目开发过程中出现了 问题就是父组件调用子组件的方法时 子组件数据还未渲染 所以需要使用$nextTick 详细用法见官方文档

<sweb-print :swebData="iframeContent" v-if="iframeContent" ref="sweb-iframe"></sweb-print>
 print () {
      this.printSupOrder().then(res => {
        this.iframeContent = res.data
        this.$nextTick(() => {
          this.$refs['sweb-iframe'].doPrint()
        })
      }).catch(err => {
        this.$message.error(err.error.msg)
      })
    }