iframe通过postMessage进行跨域通信以及在Angular中使用

写在前面

在前端开发过程中,会遇到一些需要使用iframe的场景,使用iframe关键的一个点是数据之间的传输,基于同源的要求十分苛刻,大家基本上是都是跨域的,如果跨域进行数据传输呢?

大家使用的比较多的就是postMessage()这个方法了,下面将具体展示如何在html中使用iframe进行数据传输,以及在angular框架中如何使用以及在angular中与html中的差异性

普通html页面

由外到内(向iframe内网页传输数据)

使用iframe处

javascript 复制代码
<body>
    <iframe src="./iframe-content.html" class="iframe" frameborder="0"></iframe>
    <script>
      const iframeElement = document.querySelector(".iframe");
      //需要等待iframe加载完成后再发送信息,原因是 iframe的网页需要注册message事件,若先发消息再注册,那么在注册之前是收不到消息的
      iframeElement.addEventListener("load", () => {
        //相当于iframe自己给自己发消息
        iframeElement.contentWindow.postMessage("这是一条信息", "*");
      });
    </script>
  </body>

iframe内容

javascript 复制代码
<body>
  <span>这里是iframe内容</span>
  <script>
    window.addEventListener("message", (event) => {
      console.log(event.data);
    });
  </script>
</body>

由内到外

使用iframe处

javascript 复制代码
  <body>
    <iframe src="./iframe-content.html" class="iframe" frameborder="0"></iframe>
    <script>
      window.addEventListener("message", (event) => {
        console.log(event.data);
      });
    </script>
  </body>

iframe内容

javascript 复制代码
 <body>
    <span>这里是iframe内容</span>
    <script>
      //给上层级发消息,若上层级是顶层可以使用window.top
      window.parent.postMessage("给使用处发消息", "*");
    </script>
  </body>

在Angular使用

  • 首先是src 在angular中直接使用src链接会被认为是不安全的,需要通过DomSanitizer中的bypassSecurityTrustResourceUrl方法进行一个转化才可使用
javascript 复制代码
constructor(
    private sanitizer: DomSanitizer
) {
    this.src = this.sanitizer.bypassSecurityTrustResourceUrl(`${path}`);
}
  • 其次是在获取iframe 可以通过 @ViewChild来获取
javascript 复制代码
@ViewChild('iframe') iframeElement:ElementRef<HTMLIFrameElement>; 来进行获取
  • 通过监听iframe load事件来判断接受事件是否注册不能使用了 ,就需要在iframe内部传来一条信息来通知事件是否注册完成
javascript 复制代码
  iframeElement.addEventListener("load", () => {
        iframeElement.contentWindow.postMessage("这是一条信息", "*");
      });
javascript 复制代码
  window.parent.postMessage(true); //通知app事件注册成功

  	//接受iframe来的通知 基于rxjs去写事件的监听
   fromEvent<MessageEvent>(window, 'message').pipe(map(data => data.data))
    .pipe(takeUntil(this.ngUnsubscribe$))
    .subscribe(isLoaded => {
        if (isLoaded) {
            this.templatePreviewIframe.nativeElement.contentWindow.postMessage(数据);
        }
    });

总结

html

go 复制代码
<iframe
#iframe
[src]="src"
frameborder="0"
></iframe>
go 复制代码
src:string;
ngUnsubscribe$= new Subject();
@ViewChild('iframe') iframeElement: ElementRef<HTMLIFrameElement>;
constructor(
    private sanitizer: DomSanitizer
) {
    this.src = this.sanitizer.bypassSecurityTrustResourceUrl(`${path}`);
}

ngOnInit(){
    fromEvent<MessageEvent>(window, 'message').pipe(map(data => data.data))
        .pipe(takeUntil(this.ngUnsubscribe$))
        .subscribe(isLoaded => {
            if (isLoaded) {
                this.templatePreviewIframe.nativeElement.contentWindow.postMessage(数据);
            }
        });
}

ngOnDestroy(){
    this.ngUnsubscribe$.next();
    this.ngUnsubscribe$.complete();
}

iframe内容网页

go 复制代码
ngOnInit(){
    fromEvent(window, 'message').subscribe((event: MessageEvent<any>) => {
        //todo
    });
    window.parent.postMessage(true); //通知app事件注册成功
}
相关推荐
鹿心肺语几秒前
前端HTML转PDF的两种主流方案深度解析
前端·javascript
海石19 分钟前
去到比北方更北的地方—2025年终总结
前端·ai编程·年终总结
一个懒人懒人26 分钟前
Promise async/await与fetch的概念
前端·javascript·html
Mintopia32 分钟前
Web 安全与反编译源码下的权限设计:构筑前后端一致的防护体系
前端·安全
输出输入34 分钟前
前端核心技术
开发语言·前端
Mintopia39 分钟前
Web 安全与反编译源码下的权限设计:构建前后端一体的信任防线
前端·安全·编译原理
林深现海1 小时前
Jetson Orin nano/nx刷机后无法打开chrome/firefox浏览器
前端·chrome·firefox
黄诂多1 小时前
APP原生与H5互调Bridge技术原理及基础使用
前端
前端市界1 小时前
用 React 手搓一个 3D 翻页书籍组件,呼吸海浪式翻页,交互体验带感!
前端·架构·github
文艺理科生1 小时前
Nginx 路径映射深度解析:从本地开发到生产交付的底层哲学
前端·后端·架构