如何让window.location.assign打开的页面共享原页面window对象
跨域场景下新页面访问原页面window对象的解决方案
由于浏览器同源策略限制,不同源的页面无法直接访问彼此的window对象属性和方法,结合你的需求(无法复制大量函数),以下是几种可行的解决方案:
方法1:使用window.postMessage API(推荐)
这是浏览器原生支持的跨域通信方案,通过消息传递实现原页面方法的调用,无需复制函数。
原页面(http://first-web-app.com)代码
监听新页面的调用请求,执行对应方法后返回结果:
// 监听跨域消息 window.addEventListener('message', (event) => { // 验证消息来源,仅处理可信的second-web-app.com请求 if (event.origin !== 'http://second-web-app.com') return; const { action, args } = event.data; // 检查要调用的方法是否存在于当前window if (typeof window[action] === 'function') { const result = window[action](...args); // 将结果回传给新页面 event.source.postMessage({ type: 'result', action, result }, event.origin); } });
新页面(http://second-web-app.com)代码
注意:不能用window.location.assign跳转,因为这会替换原页面,丢失原window引用,必须改用window.open打开新页面,保留原窗口的opener引用:
// 获取原页面的window引用(通过window.open打开时,原窗口引用为window.opener) const originWindow = window.opener; // 发送调用请求,比如调用原页面的getUserInfo方法 originWindow.postMessage({ action: 'getUserInfo', args: ['userId123'] }, 'http://first-web-app.com'); // 监听原页面返回的结果 window.addEventListener('message', (event) => { if (event.origin !== 'http://first-web-app.com') return; if (event.data.type === 'result' && event.data.action === 'getUserInfo') { console.log('原页面返回结果:', event.data.result); // 在这里处理结果 } });
方法2:使用SharedWorker共享工作线程
通过共享工作线程作为中间层,原页面将需要暴露的方法注册到Worker中,新页面通过Worker调用这些方法。
共享工作线程脚本(shared-worker.js)
let exposedMethods = {}; self.addEventListener('connect', (e) => { const port = e.ports[0]; port.addEventListener('message', (msg) => { // 注册原页面的方法 if (msg.type === 'register') { exposedMethods = { ...exposedMethods, ...msg.methods }; } // 调用注册的方法 else if (msg.type === 'call') { const { methodName, args } = msg.data; if (exposedMethods[methodName]) { const result = exposedMethods[methodName](...args); port.postMessage({ type: 'result', methodName, result }); } } }); port.start(); });
原页面注册方法
const worker = new SharedWorker('shared-worker.js'); worker.port.start(); // 将需要暴露的window方法注册到共享线程 worker.port.postMessage({ type: 'register', methods: { getUserInfo: window.getUserInfo, calculateTotal: window.calculateTotal // 其他需要暴露的方法 } });
新页面调用方法
const worker = new SharedWorker('shared-worker.js'); worker.port.start(); // 调用原页面注册的方法 worker.port.postMessage({ type: 'call', data: { methodName: 'getUserInfo', args: ['userId123'] } }); // 监听返回结果 worker.port.addEventListener('message', (event) => { if (event.data.type === 'result' && event.data.methodName === 'getUserInfo') { console.log('调用结果:', event.data.result); } });
注意:需要确保共享线程脚本的CORS配置允许两个源访问,同时要考虑浏览器兼容性。
方法3:抽离公共方法到独立脚本(可选)
如果原页面的方法大多是纯函数、不依赖原页面window上下文,可以将这些方法抽离成独立的JS文件,部署到允许跨域访问的位置,两个页面都引入该脚本,新页面即可直接使用这些方法。这种方式无需跨域通信,但仅适用于方法不依赖原页面上下文的场景。
内容的提问来源于stack exchange,提问作者Gavara.Suneel
相关产品推荐
相关产品推荐

