Angular项目中如何让iframe加载的组件正常响应NGXS状态变更
问题成因
iframe属于完全独立的浏览器浏览上下文,和父窗口的运行环境内存隔离。你父窗口中NGXS的状态存储在父窗口的运行内存中,iframe内加载的Angular应用会初始化完全独立的NGXS Store实例,默认不会和父窗口的Store做任何同步,因此iframe内的组件永远只能拿到自身Store初始化的默认值,这和你是否刷新iframe、是否重载iframe节点没有关系——只要没有主动做状态同步,iframe内的Store永远不会拿到父窗口更新后的状态值。
可行解决方案
不需要额外搭建NestJS后端服务,纯前端即可解决该问题,常用方案如下:
- 方案1:postMessage跨上下文通信(兼容性最好,支持跨域场景)
- 父窗口侧订阅NGXS状态变更,每次状态更新时调用
iframe.contentWindow.postMessage({ type: 'STATE_UPDATE', payload: 最新状态值 }, 你的应用同源地址)发送状态 - iframe内的应用监听
window的message事件,校验消息来源合法后,调用Store.patch/Store.set方法更新自身的NGXS Store即可同步状态
- 父窗口侧订阅NGXS状态变更,每次状态更新时调用
- 方案2:同域下直接共享父窗口Store实例(实现最简单)
仅适用于iframe加载的资源和父窗口同域的场景:- 父窗口初始化后将NGXS Store实例挂载到
window对象上,比如window.parentStore = this.store - iframe内的应用初始化时,直接取
window.parent.parentStore作为自身的状态源,或者订阅父窗口Store的变更同步到自身Store即可
- 父窗口初始化后将NGXS Store实例挂载到
- 方案3:通过URL参数传递初始化状态(配合你现有的重载逻辑)
如果你坚持用*ngIf重载iframe的方案,可以在每次状态更新时,将最新状态序列化后作为查询参数拼接在iframe的src属性上,比如src="/iframe组件地址?state=${encodeURIComponent(JSON.stringify(currentState))}",iframe加载时从location.search中解析状态值初始化自身Store即可
你预想的NestJS后端存储状态的方案也可以生效,相当于把状态存储从前端内存转移到了后端,两个上下文都通过接口拉取同一份状态,不会出现同原因的失效,只是额外增加了后端开发和接口请求开销,没有特殊需求的话不需要用这个方案。
内容的提问来源于stack exchange,提问作者Optiq
相关产品推荐
相关产品推荐

