点击事件同时触发window.open与postMessage失效问题求助
问题:同时执行“打开窗口+发送消息”的按钮失效,单独操作正常
问题描述
我有三个按钮:
myBtn:预期打开包含iframe的页面,同时发送消息修改该页面内iframe的源myBtn1:仅负责打开页面myBtn2:仅负责发送消息
单独点击myBtn1和myBtn2功能完全正常(窗口打开后,myBtn2能成功向目标窗口发送消息),但点击myBtn时,消息无法成功发送。
相关代码
HTML:
<button type="button" id="myBtn">Open and Send Message</button> <button type="button" id="myBtn1">Just Open</button> <button type="button" id="myBtn2">Just Send</button>
JavaScript:
function openNumberIndex(){ nIndex = window.open('numberindex.html'); } function sendMessage(){ let msg={nFrame: 'glossary-index.html#monad'}; nIndex.postMessage(msg,"*") nIndex.focus(); } var nIndex; var btn = document.getElementById("myBtn"); var btn1 = document.getElementById("myBtn1"); var btn2 = document.getElementById("myBtn2"); btn.addEventListener("click", openNumberIndex); btn.addEventListener("click", sendMessage); btn1.addEventListener("click", openNumberIndex); btn2.addEventListener("click", sendMessage);
问题原因
核心问题是窗口打开是异步操作:当myBtn的两个点击事件同步触发时,openNumberIndex刚调用window.open,新窗口还未完成加载初始化,此时立即执行sendMessage调用postMessage,消息会因为目标窗口未就绪而无法被正确接收。
解决方案
方案1:监听新窗口的load事件(推荐)
将“打开窗口+发送消息”合并为一个函数,等待新窗口加载完成后再发送消息,确保目标窗口就绪:
var nIndex; var btn = document.getElementById("myBtn"); var btn1 = document.getElementById("myBtn1"); var btn2 = document.getElementById("myBtn2"); // 合并打开和发送逻辑,监听窗口加载完成 function openAndSendMessage() { nIndex = window.open('numberindex.html'); nIndex.addEventListener('load', function() { let msg = {nFrame: 'glossary-index.html#monad'}; nIndex.postMessage(msg, "*"); nIndex.focus(); }); } function openNumberIndex(){ nIndex = window.open('numberindex.html'); } function sendMessage(){ let msg={nFrame: 'glossary-index.html#monad'}; nIndex.postMessage(msg,"*") nIndex.focus(); } btn.addEventListener("click", openAndSendMessage); btn1.addEventListener("click", openNumberIndex); btn2.addEventListener("click", sendMessage);
方案2:延迟发送消息(不推荐,仅临时应急)
通过setTimeout给窗口加载留缓冲时间,但这种方式依赖固定延迟,不同浏览器/设备加载速度不同,可靠性差:
function sendMessage(){ setTimeout(() => { let msg={nFrame: 'glossary-index.html#monad'}; nIndex.postMessage(msg,"*") nIndex.focus(); }, 500); // 延迟时间可根据实际情况调整 }
内容的提问来源于stack exchange,提问作者Z Zach
相关产品推荐
相关产品推荐

