在react框架中实现打印过程中踩的坑

挽枫 1927 2022-03-19

最近在做一个需求,就是需要在产品里调用打印机,实现打印票据的操作,我也是第一次做,说真的踩坑不少,希望这篇文章可以帮助到你。

TOC

前言

大家可能在react应用中实现打印功能时,可能会遇到打印出来的样式出现问题,调用完打印接口后也会出现页面样式紊乱的问题以及注册绑定的事件失效等问题,这里我介绍一种第三方库react-to-print,通过这个库实现在当前页面的打印和打印服务端传递过来的html文档这两种打印场景。

window.print()踩的坑

window.print这种方法是最原生的方法,但是鉴于react是个单页应用,在打印完毕之后,会出现dom节点绑定的事件会被注销,以及页面会空白。
读者可以自行将window.location.reload()注销掉,在调用打印方法之后,你会发现printtest失效。
通过这种办法可以实现局部打印,你只需要把print绑定到你要打印的dom节点上即可。


function App() {
  const printf = () => {
    const old = window.document.body.innerHTML;
    const printPart = document.querySelector('.print');
    window.document.body.innerHTML = '';
    window.document.body.appendChild(printPart);
    window.print();
    window.document.body.innerHTML = old;
    window.location.reload();//注意打印完毕之后主动刷新,否则系统数据页面还有注册的事件将无用
  };
  const printtest = () => {
    console.log('1234');
  }
  return (
    <div className="print">
      <header>
        这是头部信息
      </header>
      <button onClick={printtest}>事件测试</button>
      <button onClick={printf}>window.print打印</button>
    </div>
  );
}

export default App;

第三方库react-to-print介绍

使用这种库的好处是对外暴露了很友好的接口,不需要自己实现,而且也可以设置打印样式,打印完成之后页面样式不会乱,注册绑定的事件也不会失效,具体详情请参阅他的官方文档

打印当前页面

import React, { useRef } from 'react';
import { useReactToPrint } from 'react-to-print';


const App = () => {
  const printRef = useRef(null);
  const handlePrint = useReactToPrint({
    content: () => printRef.current,
  });
  const printtest = () => {
    console.log('1234');
  }
  return (
    <div ref={printRef}>
      <header>
        这是头部信息
      </header>
      <button onClick={printtest}>事件测试</button>
      <button onClick={handlePrint}>window.print打印</button>
    </div>
  );
}
export default App;

打印服务端传过来的html文档

印文打印内容一开始不知道,所以你需要给打印文档一个父节点,给父节点设置display:none,这样页面就不会展示它,而且react-to-print组件也可以copy到打印文档里的内容

import React, { useRef,useEffect } from 'react';
import { useReactToPrint } from 'react-to-print';
const App = () => {
  useEffect(() => {
    const res = getServerDocument({});//这里具体是你要请求打印文档的地址
    document.getElementById('print_box')!.innerHTML = res;
  }, [])
  const printRef = useRef(null);
  const handlePrint = useReactToPrint({
    content: () => printRef.current,
  });
  return (
    <div>
      <div style={{ display: "none" }} >
        <div id='print_box' ref={printRef}>
          
        </div>
      </div>
      <button onClick={handlePrint}>window.print打印</button>
    </div>
  );
}
export default App;

戳这里进入react-to-print官方文档