window.print() 为什么会打印两遍?

页面通过element 的 el-dialog 实现效果如下:
image.png

因为组件是独立弹窗,点击打印按钮会只打印弹窗部分,刚好和需求相符,就不用再写代码决定要打印的元素了
(ps:弹窗里右下角的打印按钮在调用window.print() 前隐藏了):
image.png

但问题是,预览中出现了两张纸,而且两张纸内容是一样的:
image.png

这我就很奇怪,如果第二张是空白页,可能是因为样式或内容导致一张纸放不下造成的,但现在两张纸是相同的内容,是什么原因引起的?

阅读 155
avatarAI BotBETA

可能的原因及解决方案:

  1. 事件冒泡导致的双重触发
  2. 检查按钮点击事件是否被重复绑定(尤其是组件嵌套时)
  3. 在打印方法前添加 e.stopPropagation()

    handlePrint(e) {
      e.stopPropagation();
      this.hideButton();
      window.print();
    }
  4. 打印样式残留问题
  5. 强制重置打印样式表

    @media print {
      @page { size: auto; margin: 0; }
      body * { 
     visibility: hidden; 
      }
      .el-dialog__wrapper {  /* 弹窗容器选择器 */
     position: absolute !important;
     left: 0 !important;
     top: 0 !important;
     width: 100% !important;
     height: auto !important;
     overflow: visible !important;
      }
      .el-dialog, .el-dialog * {  /* 弹窗本体选择器 */
     visibility: visible !important;
      }
    }
  6. 异步操作时序问题(如果隐藏按钮有动画)
  7. 确保隐藏操作完成后再执行打印

    async handlePrint() {
      await this.hideButton(); // 假设返回Promise
      setTimeout(() => { window.print(); }, 50); // 增加渲染间隙
    }
  8. 浏览器默认打印行为
  9. 强制单页打印(适用于固定高度的内容)

    @media print {
      .el-dialog {
     page-break-after: avoid !important;
     page-break-inside: avoid !important;
      }
    }

验证步骤:

  1. 打开浏览器开发者工具
  2. 在控制台输入 debugger 语句拦截打印操作
  3. 检查调用堆栈是否出现重复调用
  4. 在打印预览中通过"更多设置"查看总页数提示

备选方案:
改用iframe打印更稳定:

const printContent = document.querySelector('.dialog-content').cloneNode(true);
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
iframe.contentDocument.body.appendChild(printContent);
iframe.contentWindow.print();
setTimeout(() => iframe.remove(), 1000);
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏