Angular项目中Chrome首次调用window.print()异常的解决方法问询
Angular打印URL重置问题解决方法
问题原因
Chrome/Edge浏览器中,首次调用window.print()时,打印预览窗口的启动属于异步过程,此时浏览器尚未完全锁定页面状态,紧接着执行的router.navigate会优先修改URL,导致打印依赖的参数丢失。第二次打印时,浏览器已缓存打印上下文,不会被导航操作干扰;Naver Whale 126的Chromium内核对打印事件时序做了优化,规避了该冲突。
解决方案
方案1:监听打印完成事件再执行路由导航
通过window.onafterprint事件,确保打印预览窗口关闭后才修改路由,避免URL在打印过程中被重置。
修改print.service.ts代码:
onDataReady() { setTimeout(() => { this.isPrinting = true; window.print(); // 绑定打印完成/关闭后的回调 const afterPrintHandler = () => { this.router.navigate([{outlets: {print: null}}]).then(console.info); window.removeEventListener('afterprint', afterPrintHandler); // 移除监听防止重复触发 }; window.addEventListener('afterprint', afterPrintHandler); }); }
方案2:确保DOM完全渲染后再触发打印
利用Angular的AfterViewChecked生命周期钩子,等待数据加载完成且DOM渲染完毕后再调用打印,避免因DOM未就绪导致的打印异常。
修改label.component.ts:
import { OnInit, AfterViewChecked, ChangeDetectorRef } from '@angular/core'; export class LabelComponent implements OnInit, AfterViewChecked { private isDataReady = false; constructor(private cdr: ChangeDetectorRef) {} async ngOnInit() { this.QRwidth = 50; const dlvyDto = new MakrDlvyOrdGroupNoDto(); dlvyDto.ordNoList = this.invoiceIds; this.orderDetails = await this.rest.postDlvyPrint(dlvyDto).toPromise(); this.isDataReady = true; this.cdr.detectChanges(); // 强制触发变更检测更新DOM } ngAfterViewChecked() { if (this.isDataReady) { this.printService.onDataReady(); this.isDataReady = false; // 仅执行一次打印触发 } } }
同时调整print.service.ts,仍保留afterprint事件处理路由:
onDataReady() { window.print(); this.isPrinting = true; const afterPrintHandler = () => { this.router.navigate([{outlets: {print: null}}]).then(console.info); window.removeEventListener('afterprint', afterPrintHandler); }; window.addEventListener('afterprint', afterPrintHandler); }
方案3:临时禁用首次打印的路由导航(应急方案)
若无需立即关闭打印路由出口,可先注释掉导航逻辑,待确认打印正常后再结合上述方案优化:
onDataReady() { setTimeout(() => { window.print(); this.isPrinting = true; // 临时注释导航,测试打印正常后再恢复 // this.router.navigate([{outlets: {print: null}}]).then(console.info); }); }
内容的提问来源于stack exchange,提问作者DevRecord
相关产品推荐
相关产品推荐

