为何window.open()可用但window.close()无法关闭窗口?
window.open()打开的窗口无法用window.close()关闭的解决方案
问题诊断
你遇到的核心问题大概率是跨域限制导致的:当你通过window.open()打开不同域名的页面后,浏览器的同源策略会阻止父页面通过原窗口引用调用close()方法——哪怕你能看到关闭事件的日志输出,此时tester对象已经失去了对目标窗口的控制权。此外,如果多次点击「Probar」按钮,tester变量会被新的窗口引用覆盖,旧窗口也会无法通过原引用关闭。
解决方案
方案1:优先确保同域测试
如果你的测试URL是同域地址,原代码逻辑本身是有效的,只需补充避免重复窗口的逻辑:
d.addEventListener("submit", (e) => { if (e.target === $form) { e.preventDefault(); // 打开新窗口前先关闭旧窗口 if (tester && !tester.closed) { tester.close(); } tester = window.open( $form.direccion.value, "tester", `innerWidth=${$form.ancho.value}, innerHeight=${$form.alto.value}` ); } });
方案2:跨域场景用postMessage实现关闭
如果必须测试外域页面,可通过postMessage向子窗口发送关闭指令,让窗口自行调用close():
修改prueba_responsive.js代码:
const d = document; export default function responsiveTester(form) { const $form = d.getElementById(form); let tester; d.addEventListener("submit", (e) => { if (e.target === $form) { e.preventDefault(); // 关闭旧窗口 if (tester && !tester.closed) { tester.close(); } tester = window.open( $form.direccion.value, "tester", `innerWidth=${$form.ancho.value}, innerHeight=${$form.alto.value}` ); // 延迟注入监听脚本,确保窗口加载完成 setTimeout(() => { if (tester && !tester.closed) { tester.postMessage(` window.addEventListener("message", (event) => { if (event.data === "close-tester-window") { window.close(); } }); `, "*"); } }, 1000); } }); d.addEventListener("click", (e) => { if (e.target.name === "cerrar" && tester && !tester.closed) { console.log("Función CERRAR activada"); // 发送关闭指令 tester.postMessage("close-tester-window", "*"); } }); }
注意:实际生产环境中,应将
*替换为目标窗口的具体域名,避免安全风险。
方案3:增加异常捕获与兼容性处理
在关闭逻辑中增加错误捕获,兼容不同浏览器的限制:
d.addEventListener("click", (e) => { if (e.target.name === "cerrar") { console.log("Función CERRAR activada"); if (tester && !tester.closed) { try { tester.close(); } catch (err) { console.error("直接关闭失败,尝试跨域指令:", err); tester.postMessage("close-tester-window", "*"); } } } });
内容的提问来源于stack exchange,提问作者jrodriguezc
相关产品推荐
相关产品推荐

