<PageHeaderWrapper>
<iframe
src='xxx.url.com'
ref={this.iframeRef}
onLoad={this.adjustIframeHeight}
</PageHeaderWrapper>
子页面内使用MutationObserver来监听页面内容的变化,并在变化时通过postMessage将页面加载完成后的高度发送给父页面。
首先创建一个MutationObserver对象,用于监听子页面内容的变化。在这个例子中,将content设为
的目标,并传入配置对象{ childList: true, subtree: true }
,表示要观察子节点的添加或删除,以及整个子树的变化。
在本例中,使用了以下配置对象:{ childList: true, subtree: true }
childList
:表示要观察目标节点的子节点的变化。当子节点被添加或删除时,MutationObserver会触发回调函数。如果将childList
设置为true
,则会观察子节点的变化;如果设置为false
,则不会观察子节点的变化。
2.subtree
:表示我们要观察目标节点的整个子树的变化。当目标节点及其后代节点的属性或子节点发生变化时,MutationObserver会触发回调函数。如果将subtree
设置为true
,则会观察整个子树的变化;如果设置为false
,则只会观察目标节点本身的变化。
从而,当页面路由变化等情况发生时,页面内容的高度同时产生变化,并调用回调函数,获取到最新的页面高度content.scrollHeight
。
最后使用window.parent.postMessage
方法向父页面发送消息。配置中的'*'
表示会将消息发送给所有的父页面,即使不在同一域中。
父页面主要逻辑是在组件挂载时监听message
事件,接收来自iframe的消息,并根据消息中的高度调整iframe的高度。在组件挂载时,通过window.addEventListener
方法监听message
事件,以便接收来自iframe的消息。在组件卸载时,通过window.removeEventListener
方法移除对message
事件的监听,以避免内存泄漏。
通过监听message
事件,可以实时接收来自iframe的消息,并根据消息中的高度调整iframe的高度。这样可以确保iframe的高度始终与其内容的高度保持一致,避免出现滚动条或内容被截断的问题。
postMessage与跨域
在Web开发中,浏览器实施了同源策略(Same-Origin Policy),该策略限制了不同源(协议、域名、端口)之间的交互。这意味着在一个页面中的JS代码无法直接访问来自不同源的页面的内容或执行操作。在本项目中,由于嵌入的iframe域名与父页面域名不同,触发了同源策略,导致直接通过JS获取子页面高度的方法失效。
在iframe跨域传参的情况下,父页面和子页面属于不同的源,无法直接访问对方的内容。因此需要使用postMessage来进行跨域通信,它允许在不同窗口或标签页之间进行安全的跨域通信。通过在父页面中向子页面发送消息,或在子页面中向父页面发送消息,来实现参数的传递和交互。postMessage的跨窗口的通信方式可以绕过同源策略的限制,实现不同源页面之间的数据传递和交互。
MutationObserver
MutationObserver是一个用于监听DOM树变化的API,它可以观察DOM节点的属性、子节点等的变化,并在变化发生时触发回调函数。
MutationObserver的作用和价值在于:
监听DOM变化:MutationObserver可以帮助我们实时监听DOM树的变化,包括节点的添加、删除、属性的修改等。这对于需要实时响应DOM变化的场景非常有用,例如在动态加载内容、实时更新UI等情况下。
避免轮询:相比于传统的轮询方式,MutationObserver可以更高效地监听DOM变化。传统的轮询方式需要不断地检查DOM状态,而MutationObserver只在DOM发生变化时才会触发回调函数,避免了不必要的性能开销。
精确捕获变化:MutationObserver可以精确地捕获DOM的变化,包括细微的变化,而不仅仅是节点的添加或删除。它可以观察到属性的修改、文本内容的变化等,使我们能够更细致地处理DOM的变化。
MutationObserver在这个应用中用于监听子页面内容的变化。当内容发生变化时,MutationObserver会触发回调函数,并在回调函数中获取内容的高度,进行相应的处理。通过MutationObserver实时捕获子页面内容的变化,从而实现动态调整iframe高度的功能。
写在最后的更简单的方法
以上方法是为了去除双滚动条的办法之一,即去掉 iframe 嵌入后,页面的内滚动条,但是作为B端项目,普遍使用 antd layout 来实现后台系统,而 antd 的页头页尾的距离基本不变。若将 iframe 的高度设置为屏幕高度减去 antd 页头页尾的距离,则外部的滚动条将可以去除,同样可以实现解决两个滚动条的 bug,并且使得父项目和子项目解藕,更具稳定性和复用性。
<iframe
style={{
width: '100%',
// 240 为 antd layout 的页头及页尾整体需要的高度,需要从屏幕高度中去除,以使得iframe嵌入后,去除外部页面滚动条
height: `${screenHeight - 240}px`,
height="100%"
src='xxx.url.com'
粉丝