子页面如何获取父页面中iframe标签上的属性?

3,587 阅读2分钟

「这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战

背景

最近开发的一个项目,通过 iframe 嵌入到第三方系统,需要获取拼接在当前iframe的src上的query参数来作为接口请求的身份验证,那么,如何在自己的系统中获取第三方系统通过ifrme传过来的query参数呢?

使用iframe通过iframe子页面调用父页面或父页面调用iframe子页面时,由于违反了浏览器安全策略,是无法跨iframe获取到另一页面的数据,在控制台中可以看到如下报错:

Blocked a frame with origin “http://localhost:\*\*\*\*” from accessing a cross-origin frame.

解决方案

iframe 父子之间通常是通过 postMessage 方法进行通信。回到我们的问题,我们要获取在第三方系统传递过来的query参数,可以PostMessage 进行数据传递。

1、父页面调用 iframe 子页面

  • 父页面数据发送

在父页面中,获取到当前的iframe,然后通过 postMessage 方法发送数据,postMessage 方法中的data为需要发送的数据:

document.getElementById('iframe').contentWindow.postMessage(data,'*')
// iframeRef.current.contentWindow.postMessage(data,'*')  // react 通过 ref 获取 iframe 
  • 子页面接收数据

在子页面中,通过 addEventListener 方法监听 message 事件:

addEventListener('message', e => {
    // e.data为父页面发送的数据
    console.log(e.data)
})

postMessage 通信的方案需要第三方系统配合,往往需要第三方系统进行改造,这显然不是一个好的解决方案。还有一个方案不需要第三方系统配合,只需要在我们自己的页面中直接获取就可以了。

2、window.location 获取 iframe 的src

当通过 iframe 嵌入页面时,实际上是发生了路由的变化, 因此我们可以通过 window.location 获取被嵌入页面的链接:

export const getPageQueries = (path?: string) => {
  const query = {}
  path = path || window.location.href;
  const urlObj = new URL(path);
  const search = urlObj.search;

  if (search) {
    const arr = search.replace(/\#\/.*\?/, '').split('&');
    arr.forEach((item: string) => {
      const [key, value] = item.replace('?', '').split('=');
      query[key] = value
    })
  }
  return query
}

3、umi/router 的 history 对象获取 src

如果我们的前端项目使用的是 umi 框架,我们可以通过 umi/router 的 history 对象获取当前的路由信息:

import { history } from 'umi';

const getQuery = () => {
	const query = history.location.query;
  return query;
}