Chrome调用window.print()关子窗口致父窗口输入框失效问题咨询
现象定性
该现象是Chromium内核的已知遗留Bug,并非业务代码逻辑错误。
触发逻辑为:子窗口调用window.print()唤起打印预览时,Chromium会启动全局模态输入锁,拦截所有非打印预览区域的输入事件,保证预览窗口的模态优先级;如果用户未点击打印/取消按钮关闭预览,直接关闭承载打印逻辑的子窗口,内核不会主动回收这个全局输入锁,最终导致同渲染进程下的父窗口所有输入控件被锁,表现为无法输入的类disabled状态。
该Bug在Chrome 70~Chrome 117的稳定版本中均可稳定复现,基于Chromium开发的Edge、360浏览器、QQ浏览器等对应版本也存在相同问题,Chrome 118之后的版本已对该回收逻辑做了修复。
可行规避方案
- 子窗口侧前置拦截关闭逻辑
在子窗口监听beforeunload事件,窗口关闭前主动抢占焦点、释放打印上下文,避免输入锁残留,参考代码:
// 子窗口内注入逻辑 window.addEventListener('beforeunload', () => { // 主动拉取焦点,触发内核打印状态检测 window.focus(); // 主动终止打印会话,清除预览模态锁 if (window.matchMedia) { const printMedia = window.matchMedia('print'); printMedia.removeListener(() => {}); } });
- 父窗口侧做兜底状态恢复
父窗口在唤起子窗口后,轮询检测子窗口关闭状态,子窗口关闭时主动触发焦点重置、输入层重绘,强制解除残留锁,参考代码:
// 父窗口唤起子窗口逻辑 const childWindow = window.open('./child-page', '_blank', 'width=800,height=600'); const closeChecker = setInterval(() => { if (childWindow.closed) { clearInterval(closeChecker); // 强制父窗口重获焦点 window.focus(); // 触发文档输入层重绘,解除残留锁 document.body.tabIndex = -1; document.body.focus(); document.body.removeAttribute('tabindex'); } }, 150);
- 交互路径阻断
从产品交互层面避免触发Bug的路径:子窗口调用window.print()后,临时隐藏子窗口的关闭按钮、拦截关闭动作,直到afterprint事件触发(即用户完成打印/取消操作、打印预览关闭)后,再允许子窗口被关闭,从根源上跳过触发Bug的操作路径。
内容的提问来源于stack exchange,提问作者kinglion VistaJIN
相关产品推荐
相关产品推荐

