likes
comments
collection
share

记一次原生实现浏览器打印功能

作者站长头像
站长
· 阅读数 4

记一次实现浏览器打印功能

刚好遇到项目需要实现浏览器原生打印需求,浏览器原生API window.print() 方法可以满足基础打印需求,同时也会遇到各种各样的问题

打印问题汇总

  1. 调用 window.print() 打印会打印整个document页面
  2. 当然也可以用 document.body.innerHTML 来置换页面内容,但是使用框架的小伙伴们就得用 window.location.reload() 来刷新页面,用户体验上不是很好,这个问题下方有更优化的打印方案
doPrint() {
         const html = document.getElementById('XXX').innerHTML
          // 赋值打印的区域,进行打印
          window.document.body.innerHTML = html
          // 防止样式丢失,添加样式文件
          document.body.appendChild(this.getStyle())
          // 调用window打印方法
          window.print() 
          // 打印完成后重新加载页面
          window.location.reload() 
     },
getStyle() {
      // 获取样式
      let linkTag = document.createElement('link')
      linkTag.id = 'commonstyle'
      linkTag.href = `/XXX/doPrint.css`
      linkTag.setAttribute('rel', 'stylesheet')
      linkTag.setAttribute('type', 'text/css')
      return linkTag
    }
  1. 打印样式添加方式
  • 引入css样式:一定要添加 media="print"
<link href="XXX.css" media="print" rel="stylesheet" />
  • style使用内联 media 属性
<style media="print"> 
    @page {
        // 可以设置打印的css样式
        margin: 0;
    }
</style>
  • 使用 @media print 媒体查询
@media print { 
    // 内容同上style
}

有没有一种更贴近用户体验的打印方式?

优化打印效果

  1. 不使用 document.body.innerHTML 来置换页面内容,改为生成 iframe 打印
doPrint() {
      try {
        // 获取需要打印区域的id
        const oldStr = document.getElementById('需要打印区域Id')
        let newStr = document.createElement('IFRAME')
        document.body.appendChild(newStr)
        let doc = newStr.contentWindow.document
        // 这里可以自定义样式
        doc.write(
          `<html>
            <head>
              <meta charset="utf-8">
              <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
              <link rel="stylesheet" href="/XXX/doPrint.css" type="text/css">
            </head>
             <!--zoom缩放页面适配打印纸张大小的效果-->
            <body style="zoom: 0.7;">
              <div id="printchart">
                ${oldStr.innerHTML}
              </div>
            </body>
          </html>`
        )
        doc.close()
        // 为iframe添加Id方便后续操作
        newStr.setAttribute('id', 'printIframe')
        newStr.setAttribute('frameborder', '0')
        newStr.setAttribute(
          'style',
          'position:absolute;width:0;height:0;left:-500px;top:-500px;'
        )
        newStr.contentWindow.focus()
        newStr.contentWindow.onload = function () {
          newStr.contentWindow.print()
          // 去除iframe元素
          document.body.removeChild(newStr)
        }
      } catch (error) {
        console.log(error)
      }
    }

总结

无论是 document.body.innerHTML 置换页面内容,还是生成 iframe 实现打印,满足项目和业务需求才是最终目标,不满足的情况下调用一些现有的js库实现打印功能也可以,本文更多的是记录

如果大家有更好的方案,欢迎留言交流!!!