You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测同一主域名下多子域名的多标签页?

跨子域名检测多标签页的可行方案

你提到的Broadcast Channel API受限于同源策略无法直接跨子域名通信,但同一主域名下的子域名可以通过以下几种方法实现多标签页检测:

1. 主域名共享Cookie + 定时轮询

所有子域名页面都能读写主域名级别的Cookie(设置domain=.example.com),通过这个Cookie维护当前打开的标签页信息:

  • 页面加载时生成唯一标识(如UUID),将标识和当前子域名写入主域名Cookie的列表
  • 定时(1-2秒)读取Cookie,检查列表中是否存在其他子域名的标签页标识
  • 页面关闭/切换至后台时,从Cookie列表移除自身标识(结合beforeunload和visibilitychange事件提升可靠性)

示例代码:

// 生成当前标签页唯一ID
const tabId = crypto.randomUUID();
const currentDomain = window.location.hostname;

// 更新主域名Cookie中的标签页列表
function updateTabList() {
  const existingTabs = JSON.parse(document.cookie.replace(/(?:(?:^|.*;\s*)tabList\s*=\s*([^;]*).*$)|^.*$/, "$1") || "[]");
  // 移除当前标签页的旧记录(避免重复)
  const updatedTabs = existingTabs.filter(tab => tab.id !== tabId);
  updatedTabs.push({ id: tabId, domain: currentDomain });
  // 设置主域名Cookie,有效期1小时
  document.cookie = `tabList=${JSON.stringify(updatedTabs)}; domain=.example.com; path=/; max-age=3600; SameSite=Lax`;
}

// 定时检测其他子域名标签页
setInterval(() => {
  const tabList = JSON.parse(document.cookie.replace(/(?:(?:^|.*;\s*)tabList\s*=\s*([^;]*).*$)|^.*$/, "$1") || "[]");
  const otherDomains = tabList.filter(tab => tab.domain !== currentDomain && tab.id !== tabId).map(tab => tab.domain);
  if (otherDomains.length > 0) {
    console.log(`检测到其他子域名标签页:${otherDomains.join(', ')}`);
    // 在这里执行你的业务逻辑
  }
}, 1000);

// 页面卸载时移除自身标识
window.addEventListener('beforeunload', () => {
  const existingTabs = JSON.parse(document.cookie.replace(/(?:(?:^|.*;\s*)tabList\s*=\s*([^;]*).*$)|^.*$/, "$1") || "[]");
  const updatedTabs = existingTabs.filter(tab => tab.id !== tabId);
  document.cookie = `tabList=${JSON.stringify(updatedTabs)}; domain=.example.com; path=/; max-age=3600; SameSite=Lax`;
});

// 页面加载时初始化
updateTabList();

注意:Cookie有4KB大小限制,标签页过多时需优化存储格式;若浏览器崩溃导致beforeunload未触发,可在定时更新时添加超时逻辑清理无效标识。

2. 统一设置document.domain为主域名(需谨慎)

如果所有子域名页面都设置document.domain = 'example.com',它们会被视为同源,此时可直接使用Broadcast Channel API或SharedWorker:

  • 在每个子域名页面开头添加:
document.domain = 'example.com';
  • 之后正常使用Broadcast Channel:
const bc = new BroadcastChannel('cross-subdomain-channel');

// 发送当前域名信息
bc.postMessage({ type: 'tab-open', domain: window.location.hostname });

// 监听其他标签页消息
bc.addEventListener('message', (event) => {
  if (event.data.type === 'tab-open' && event.data.domain !== window.location.hostname) {
    console.log(`检测到来自${event.data.domain}的标签页`);
  }
});

局限性:

  • 所有子域名必须部署HTTPS(部分浏览器对HTTP下的document.domain设置有严格限制)
  • 可能影响页面其他同源策略相关功能(如第三方脚本、iframe)

3. 主域名隐藏iframe桥接

在每个子域名页面嵌入主域名(example.com)下的隐藏iframe,通过iframe作为中间层实现跨子域名通信:

  • 主域名下创建bridge.html,负责维护所有连接的子域名标签页信息
  • 子域名页面嵌入<iframe src="https://example.com/bridge.html" style="display:none"></iframe>
  • 子域名页面通过postMessage向iframe发送自身域名,iframe将信息广播给所有连接的子域名iframe,再由iframe转发给父页面

该方法兼容性好,但需额外维护主域名下的桥接页面,通信流程相对复杂。


内容的提问来源于stack exchange,提问作者lardfler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 23:42:49