export const printPdf = (data: any) => {
  const newBlob = new Blob([data], { type: 'application/pdf' })
  const fileLink = window.URL.createObjectURL(newBlob)
  const iframe = document.createElement('iframe')
  iframe.src = fileLink
  iframe.id = 'print_pdf'
  iframe.name = 'print_pdf'
  // iframe.style.display = 'none'
  iframe.onload = () => {
    iframe.contentWindow!.addEventListener('afterprint', () => {
      document.body.removeChild(iframe)
    })
  }
  document.body.appendChild(iframe)
  window.frames['print_pdf'].focus()
  window.frames['print_pdf'].print()
}




因此,在iframe执行打印后,什么也没发生。但是,在对话框关闭后打印主页时。侦听器iframe.contentWindow!.addEventListener('afterprint', ()开始执行。为什么iframe不监听自身的打印事件?

最佳答案

这是因为您在调用print()方法之前没有等待帧内容已加载,而是在附加事件侦听器之前等待。
因此,在您附加事件监听器之前,将出现打印对话框,这将阻止js,然后触发print事件,然后附加事件。

如果在页面加载后确实调用print(),则将出现正常行为,并且监听器将触发:https://jsfiddle.net/xonq5r37/

iframe.onload = () => {
  iframe.contentWindow!.addEventListener('afterprint', (evt) => {
    document.body.removeChild(iframe)
  });
  window.frames['print_pdf'].focus()
  window.frames['print_pdf'].print()
};




至于为什么在您在主窗口上调用print()时在框架的窗口上触发该事件,这很正常,因为iframe是要打印的文档的一部分,所以它也会收到此事件。

the specs


  用户代理必须在正在打印的afterprintrelevant global object以及其中的任何nested browsing contexts中触发一个名为Document的事件。

09-25 19:21
查看更多