父窗口如何获知子窗口中哪个按钮被点击?
JavaScript父窗口如何获知子窗口按钮点击状态
问题描述
父窗口中如何获知子窗口里哪个按钮被点击(或是否有按钮被点击)?
我有一个Node函数用于构建HTML页面并创建如下按钮:
tosend += "</pre> <center> <button id='abort' onclick='window.close() '>Cancel/Abort</button> " + "<button id='acceptid' type='button' " + "onclick='window.close();'>Accept & Close</button> </center> </body> </html>";
Node将HTML返回给父客户端,父客户端创建子窗口并等待用户响应,代码如下:
ws.onmessage = function(e) { const w = window.open('about:blank'); w.document.open(); w.document.write(e.data); w.document.close(); /* wait for user to confirm */ const timer = setInterval(() => { tosend = ""; if (w.document.getElementById("acceptid").clicked == true) { /* placeholder, see note below */ tosend = "acceptid button clicked"; } else { tosend = "none"; } if (w.closed) { clearInterval(timer); ... ... } }, 500); }
注:我知道.clicked并非有效属性,仅作为占位符使用。
解决方法
1. 修改子窗口按钮的点击逻辑
在Node构建HTML的代码中,给按钮添加向父窗口传递点击状态的逻辑,通过window.opener.postMessage把点击动作发送给父窗口:
tosend += "</pre> <center> <button id='abort' onclick='window.opener.postMessage({action: \"abort\"}, \"*\"); window.close() '>Cancel/Abort</button> " + "<button id='acceptid' type='button' " + "onclick='window.opener.postMessage({action: \"accept\"}, \"*\"); window.close();'>Accept & Close</button> </center> </body> </html>";
注意:
"*"表示允许所有源,若父窗口和子窗口是同域,建议替换为具体域名(比如"http://localhost:3000"),提升安全性。
2. 父窗口监听消息事件
去掉父窗口的轮询逻辑,改为监听子窗口发来的消息,实时获取点击状态:
ws.onmessage = function(e) { const w = window.open('about:blank'); w.document.open(); w.document.write(e.data); w.document.close(); // 监听子窗口发送的消息 const messageHandler = function(event) { // 验证消息来源(可选但推荐) // if (event.origin !== "你的子窗口域名") return; let tosend = ""; switch(event.data.action) { case "accept": tosend = "acceptid button clicked"; break; case "abort": tosend = "abort button clicked"; break; default: tosend = "none"; } // 这里添加处理tosend的业务逻辑 console.log(tosend); // 子窗口关闭后可以移除监听 if (w.closed) { window.removeEventListener('message', messageHandler); } }; window.addEventListener('message', messageHandler); }
3. 优势说明
- 相比轮询,
postMessage是实时触发的,性能更优,不会浪费资源。 - 支持跨域场景(只要配置正确的
origin),通用性更强。 - 逻辑更清晰,避免了轮询可能出现的DOM访问问题(比如子窗口未加载完成时获取元素失败)。
内容的提问来源于stack exchange,提问作者Marshall
相关产品推荐
相关产品推荐

