场景: 在一个新增物资的页面上,我要点击按钮,执行 window.open()打开人员录入的工单。在人员工单上,我要填写完信息,点击提交按钮,就会产生一个人员申请的id出来。在提交完以后,我想要这个人员申请的id传到新增物资的页面上来。
解决方案:
使用 window.open()
打开新页面,这意味创建了一个完全独立的浏览器窗口/标签页,与原页面是两个独立的文档环境。
这两个页面的通信方式如下:
方案一:使用 postMessage API(推荐)
这是跨窗口通信的标准方式:
javascript
javascript
// 在原页面打开新窗口时
const newWindow = window.open(`/page/tickets/visitor/new`, '_blank');
// 监听来自新窗口的消息
window.addEventListener('message', (event) => {
// 验证消息来源(安全考虑)
if (event.origin !== window.location.origin) return;
if (event.data.type === 'PERSON_CREATED') {
const { id } = event.data.payload;
// 更新页面上的 ID 显示
setId(id);
}
});
// 在新页面提交成功后
// window.opener 指向打开当前窗口的窗口
window.opener.postMessage({
type: 'PERSON_CREATED',
payload: { id: newPersonId }
}, window.location.origin);
// 关闭当前窗口
window.close();
方案二:使用 localStorage + 轮询(适用于不能修改新页面的情况)
javascript
javascript
// 在原页面中
const newWindow = window.open(`/page/tickets/visitor/new`, '_blank');
// 轮询检查 localStorage 中是否有新创建的 ID
const checkForNewId = setInterval(() => {
const newPersonData = localStorage.getItem('newPersonCreated');
if (newPersonData) {
const { id } = JSON.parse(newPersonData);
setId(id);
localStorage.removeItem('newPersonCreated');
clearInterval(checkForNewId);
}
}, 1000);
// 在新页面提交成功后
localStorage.setItem('newPersonCreated', JSON.stringify({ id: newPersonId }));
window.close();
方案三:URL 参数传递 + 页面刷新监听
javascript
javascript
// 在原页面中
const newWindow = window.open(`/page/tickets/visitor/new`, '_blank');
// 监听新窗口关闭事件
const checkWindowClosed = setInterval(() => {
if (newWindow.closed) {
// 检查是否创建了新人员
const newPersonId = sessionStorage.getItem('newPersonId');
if (newPersonId) {
setId(newPersonId);
sessionStorage.removeItem('newPersonId');
}
clearInterval(checkWindowClosed);
}
}, 500);
// 在新页面提交成功后
sessionStorage.setItem('newPersonId', newPersonId);
window.close();
对于跨窗口通信场景,我最推荐使用方案一(postMessage API) ,因为:
- 它是现代浏览器提供的标准跨窗口通信方式
- 安全性更好(可以验证消息来源)
- 实时性更强(不需要轮询)
- 符合 Web API 的最佳实践
根据你项目的情况和安全要求,选择最适合的方案即可。