我有一个可以打开多个外部弹出窗口的网络应用程序,例如:
window.open('https://stackoverflow.com/', 'stackoverflow')
最终用户可以打开我的应用程序的多个窗口,但我希望目标只存在一个窗口。我采用的解决方案是
BroadcastChannel
,用于在我的应用程序实例之间共享信息(如果目标窗口已打开)。
broadcastChannel.postMessage({ type: 'open', value: 'stackoverflow'});
window.open('https://stackoverflow.com/', 'stackoverflow');
所有应用程序实例都会侦听消息并收集打开的目标窗口
const openWindowsTarget = [];
broadcastChannel.onmessage = (event) => {
if( event.data.type === 'open' ){
openWindowsTarget.push(event.data.value);
}
}
这样,如果在某处打开目标窗口,则该窗口将在没有 url 的情况下打开,仅带有目标
if (openWindowsTarget.includes('stackoverflow') ) {
window.open('', 'stackoverflow');
}
这样窗口只是聚焦,无需重新加载。
此行为在过去有效,但在当今,效果是打开一个新的“about:blank”窗口。可能是浏览器端发生了一些变化。
我正在寻找解决方案来修复!
为了测试/帮助将此代码段保存到 html 文件(example.html)中,打开两个单独的窗口并单击按钮
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<button onclick="openWindow('https://stackoverflow.com/', 'stackoverflow')">
Open stackoverflow
</button>
<script>
const broadcastChannel = new BroadcastChannel('WindowService');
const openWindowsTarget = [];
broadcastChannel.onmessage = (event) => {
if (event.data.type === 'open') {
openWindowsTarget.push(event.data.value);
console.log({openWindowsTarget})
}
};
function openWindow(url, target) {
if (openWindowsTarget.includes(target)) {
window.open('', target);
} else {
broadcastChannel.postMessage({ type: 'open', value: target });
openWindowsTarget.push(target);
window.open(url, target);
}
}
</script>
</body>
</html>
我也尝试过改变方法并发送广播消息以将窗口聚焦,但是
focus()
没有效果,如果窗口最小化,它仍然最小化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<button onclick="openWindow('https://stackoverflow.com/', 'stackoverflow')">
Open stackoverflow
</button>
<script>
const broadcastChannel = new BroadcastChannel('WindowService');
const openWindowsTarget = [];
const localWindows = {};
broadcastChannel.onmessage = (event) => {
if (event.data.type === 'open') {
openWindowsTarget.push(event.data.value);
console.log({openWindowsTarget})
}
if (event.data.type === 'focus') {
if( localWindows[event.data.value] ){
localWindows[event.data.value].focus();
}
}
};
function openWindow(url, target) {
if (openWindowsTarget.includes(target)) {
broadcastChannel.postMessage({ type: 'focus', value: target });
} else {
broadcastChannel.postMessage({ type: 'open', value: target });
openWindowsTarget.push(target);
localWindows[target] = window.open(url, target);
}
}
</script>
</body>
</html>
还有其他想法吗?
也许检查窗口是否存在的解决方案是合适的。虽然你原来的脚本没有给我带来任何问题。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<script>
let windowObjectReference = null; // global variable
function openRequestedTab(url, windowName) {
if (windowObjectReference === null || windowObjectReference.closed) {
windowObjectReference = window.open(url, windowName);
} else {
windowObjectReference.focus();
}
}
</script>
<body>
<button onclick="openRequestedTab('https://stackoverflow.com/', 'stackoverflow')">
Open or create a window named `stackoverflow`
</button>
</body>
</html>