Angular2-成功获取iframe.contentwindow,错误调用PostMessage()



我有一个Angular 2项目和一个NodeJS项目。我在Angular 2应用程序中有一个iFrame,我想在其中显示Nodejs应用程序。我想使用从Angular2到Nodejs的Postmessage()方法,然后反向(从Nodejs到Angular2)。Angular2地址为http://localhost:3001和nodejs地址是http://localhost:3005。

在Angular 2中,我在类分中具有一个模板;

template: `<iframe id="ifrm" #ifrm [src]="iframeURL()" width="500" height="200"> <p> Your browser does not support iframes</p> </iframe> `


iframeurl()方法主体在模板中使用;

iframeURL() {
 return this.sanitizer.bypassSecurityTrustResourceUrl('http://localhost:3005');
}


运行应用程序时,我可以在Angular2中查看IFRAME中的页面。但是,当我想获得iframe的contentWindow(下面的代码)时,我会得到以下说明(不是错误);

@ViewChild('ifrm') iframe: ElementRef;

例外:壮观感:阻止了用原点的框架 从访问跨孔框架的" http://localhost:3001"。


当我使用以下内容的postmessage()方法时,我会得到例外;

this.iframe.nativeElement.contentWindow.postMessage('{}','http://localhost:3005');

未能在" domwindow"上执行" postmessage':目标原点 提供('http://localhost:3005')与收件人不匹配 Window的Origin('http://localhost:3001')。


顺便说一句,我使用角路由打开此组件页面。整个组件代码如下:

import {Component, OnInit, ElementRef} from '@angular/core';
import {DomSanitizer} from '@angular/platform-browser'
import {ViewChild} from "@angular/core/src/metadata/di";
@Component({
    selector: 'app',
    template: `<div> <iframe id="ifrm" #ifrm [src]="iframeURL()" width="500" height="200" style="/*display:none;*/"> <p> Your browser does not support iframes</p> </iframe> </div>`
})
export class AppComponent implements OnInit{
    constructor(private sanitizer: DomSanitizer){}
    @ViewChild('ifrm') iframe: ElementRef;
    ngOnInit(){
        console.log(this.iframe.nativeElement.contentWindow);
        this.iframe.nativeElement.contentWindow.postMessage('{}', 'http://localhost:3005');
    }
    iframeURL() {
        return this.sanitizer.bypassSecurityTrustResourceUrl('http://localhost:3005');
    }
}

这就是我处理问题的方式。ngAfterViewInit之后仅postMessage。尽管它可能对您不起作用,但您可以尝试:

<iframe #iframe class="iframe-map" (load)="onIframeLoad()"></iframe>
import { Component, AfterViewInit, ChangeDetectionStrategy, ViewChild, ElementRef, Inject, Optional, Renderer } from '@angular/core';
import { URLSearchParams } from '@angular/http';
import { DialogRef, ModalComponent } from 'angular2-modal';
import { BSModalContext } from 'angular2-modal/plugins/bootstrap';
import { stringify } from 'querystringify';
import { AmapPickerOptions, AmapLocation, AMAP_PICKER_OPTIONS, AMAP_KEY, stringify as amapstringify } from '../amap';
export class AmapPickerModalData extends BSModalContext {
  public center: string;
}
@Component({
  selector: 'amap-picker-modal',
  templateUrl: './modal.component.html',
  styleUrls: ['./modal.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AmapPickerModalComponent implements ModalComponent<AmapPickerModalData>, AfterViewInit {
  @ViewChild('iframe') iframe: ElementRef;
  receiveMessage: EventListener;
  private isInited: boolean;
  constructor(
    @Inject(AMAP_KEY) private key: string,
    @Optional() @Inject(AMAP_PICKER_OPTIONS) private options: AmapPickerOptions,
    private renderer: Renderer,
    public dialog: DialogRef<AmapPickerModalData>) { }
  ngOnInit() {
    let center = this.dialog.context.center;
    this.options = Object.assign({ key: this.key }, this.options, center && { center });
    let query = stringify(this.options, true);
    this.renderer.setElementProperty(this.iframe.nativeElement, 'src', `https://m.amap.com/picker/${query}`)
    this.receiveMessage = (event: MessageEvent) => {
      if (event.origin !== 'https://m.amap.com') {
        return;
      }
      this.dialog.close(amapstringify(<AmapLocation>event.data));
    };
  }
      ngAfterViewInit() {
        this.isInited = true;
      }
  ngOnDestroy() {
    window.removeEventListener('message', this.receiveMessage);
  }
  onIframeLoad() {
    if (this.isInited) {
      setTimeout(() => {
        this.iframe.nativeElement.contentWindow.postMessage('hello', 'https://m.amap.com/picker/');
        window.addEventListener('message', this.receiveMessage, false);
      }, 500);
    }
  }
}

用于简化代码,您可以使用Angular的Renderer2,您可以使用标签名称而不是ElementRef来获取iframe元素。

import { Component, Renderer2, AfterViewInit } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
@Component({
  selector: 'app-root',
  template: `<iframe [src]="iframeURL" #iframeTagName (load)="loadIframe(iframeTagName)" style="visibility: hidden; position: absolute; left: 0; top: 0; height:0; width:0; border: none;"><iframe>`
})
export class AppComponent implements AfterViewInit {
  iframeURL;
  private isInited;
  constructor(
    private domSanitizer: DomSanitizer,
    private renderer: Renderer2
  ) {
    this.iframeURL= this.domSanitizer.bypassSecurityTrustResourceUrl('http://iframe-url.com');
  }
  loadIframe(iframeTagName) {
    if (this.isInited) {
      // post message to iframe
      iframeTagName.contentWindow.postMessage('message' , 'http://iframe-url.com');
      // You can receive response from iframe if any
      this.renderer.listen('window', 'message', (event) => {
        if (event.origin !== 'http://iframe-url.com') {
          return;
        }
        // handle event here
     });
   }
   ngAfterViewInit() {
      this.isInited = true;
   }
}

最新更新