前端-实现页面局部打印[无需内联样式]

55 阅读1分钟

1.页面节点

<div class="report">
    <n-button type="primary" class="btn-print" @click="printImage">打印</n-button>
    <div ref="printNodeEle" class="printNode">
        任意内容,可以包含各种组件库组件
        <div>你在干什么?这行会打印出来</div>
        <div class="not-print">我是需要显示,但不需要打印的内容. 这行不会打印</div>
    </div>
</div>

2.实现方式

const printImage = async () => {
    nextTick(() => {
      // 临时隐藏 not-print 类的元素
      const notPrintElements = printNodeEle.value.querySelectorAll(".not-print");
      const originalDisplays = Array.from(notPrintElements).map((el: any) => el.style.display);
      notPrintElements.forEach((el: any) => {
        el.style.display = "none";
      });
      html2canvas(printNodeEle.value, { windowHeight: printNodeEle.value.offsetHeight }).then(
        function (canvas) {
          const imgUrl = canvas.toDataURL("image/png");

          // 创建一个新的 iframe 用于打印
          const iframe = document.createElement("iframe");
          iframe.style.position = "absolute";
          iframe.style.top = "-10000px";
          document.body.appendChild(iframe);

          // 获取 iframe 的文档对象
          const iframeDocument = iframe.contentWindow?.document || iframe.contentDocument;

          // 将图像插入到 iframe 中
          iframeDocument?.open();
          iframeDocument?.write(`
      <html>
        <head>
          <title>打印</title>
        </head>
        <style>
         body {
          margin:0;
         }
        </style>
        <body>
          <img src="${imgUrl}" alt="" style="max-width: 100%; height: auto;">
        </body>
      </html>
    `);
          iframeDocument?.close();

          setTimeout(() => {
            // 打印 iframe 中的内容
            iframe.contentWindow?.focus();
            iframe.contentWindow?.print();
          });

          // 移除 iframe
          iframe.contentWindow?.addEventListener("afterprint", () => {
            document.body.removeChild(iframe);
            isPrint.value = false;
            // 恢复 not-print 类的元素的显示状态
            notPrintElements.forEach((el: any, index: number) => {
              el.style.display = originalDisplays[index];
            });
          });
        }
      );
    });
  }