怎么监听iframe

监听iframe的滚动事件,首先要获取到iframe的滚动元素contentWinow,这里例如是id名为iframeContainer

一、同源时监听

//先获取iframe的元素,因为iframe是嵌入到html里去的,所以应该获取iframe的contentWinow元素(重要!!)
let iframeContainer = document.getElementById('iframeContainer');
let iframeContentScroll = iframeContainer.contentWindow;
//接下来是用react的useEffect()进行监听
useEffect(()=>{

let handerScroll = ()=>{
   let scrollTop = iframeContentScroll.scrollTop;
    console.log('scrollTop',scrollTop);
   /*
      接下来就可以根据监听到的scrollTop做想做的操作了
   */
}

if(iframeContentScroll){
  iframeContentScroll.addEventListener('scroll', handlerScroll);
}

return ()=>{
  iframeContentScroll.removeEventListener('scroll',handlerScroll);
}

},[])

二、跨域时监听

// 特征检测法
const iframe = document.getElementById('crossOriginFrame');

const observer = new MutationObserver((mutations) => {
  if (iframe.offsetHeight > 500) {
    console.log('检测到 iframe 尺寸变化');
  }
});

observer.observe(iframe, {
  attributes: true,
  attributeFilter: ['style', 'class']
});

提问:监听iframe为什么一定要监听contentWindow?

回答:这就涉及到了iframe和DOM的知识。iframe元素本身是一个包含独立文档的容器,每个iframe都有自己的window对象,即contentWindow,而该window对象又包含document。同源策略在这里起关键作用,如果iframe的内容来自不同源,父页面无法直接访问其内部的document对象。尝试过类似iframeElement.document.addEventListener(...)这样的代码,但发现不起作用,甚至报错。这是因为直接访问iframe的document属性在跨域情况下会被浏览器阻止,导致无法获取到内部的document对象。因此,正确的做法是通过contentWindow来访问,但这也受同源策略的限制。
首先,iframe元素本身的document属性并不存在,或者即使存在,也可能只是表示iframe作为HTML元素在父文档中的节点,而不是其内部的内容文档。要访问内部文档,必须通过contentWindow.document,但这只有在同源的情况下才允许
contentWindow的作用:contentWindow是iframe内部窗口的引用,通过它可以访问到iframe的全局对象,包括document。但是,由于安全限制,如果iframe的源与父页面不同源,这种访问会被阻止,导致无法获取到document。因此,监听contentWindow的事件或通过postMessage方法进行跨域通信是必要的。

还需要提到事件监听的正确方法,例如使用load事件来确保iframe加载完成后再访问contentWindow,或者使用message事件来处理跨域通信。同时,要强调同源策略的重要性,以及在这种情况下如何安全地实现通信。

posted @ 2025-04-01 17:56  码磊姐姐  阅读(191)  评论(0)    收藏  举报