我有一个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;
}
}