回答(6)
2 years ago
构造组件时,将其自身分配给全局变量 . 然后你可以从那里引用它并调用方法 . 不要忘记使用 zone.run(() => { ... }) ,以便Angular获得有关所需更改检测运行的通知 .
function callbackfunction(){
// window['angularComponentRef'] might not yet be set here though
window['angularComponent'].zone.run(() => {
runThisFunctionFromOutside();
});
}
constructor(private _ngZone: NgZone){
window['angularComponentRef'] = {component: this, zone: _ngZone};
}
ngOnDestroy() {
window.angularComponent = null;
}
在浏览器控制台中,您必须从 切换到 plunkerPreviewTarget.... ,因为Plunker在 iFrame 中执行代码 . 然后跑
window['angularComponentRef'].zone.run(() => {window['angularComponentRef'].component.callFromOutside('1');})
要么
window.angularComponentRef.zone.run(() => {window.angularComponentRef.componentFn('2');})
An alternative approach
2 years ago
我基本上跟着this answer,但我不想让我的"outside"代码知道关于NgZone的任何信息 . 这是app.component.ts:
import {Component, NgZone, OnInit, OnDestroy} from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: 'app.component.html'
})
export class AppComponent implements OnInit, OnDestroy {
constructor(private ngZone: NgZone) {}
ngOnInit() {
window.my = window.my || {};
window.my.namespace = window.my.namespace || {};
window.my.namespace.publicFunc = this.publicFunc.bind(this);
}
ngOnDestroy() {
window.my.namespace.publicFunc = null;
}
publicFunc() {
this.ngZone.run(() => this.privateFunc());
}
privateFunc() {
// do private stuff
}
}
我还必须为TypeScript添加一个定义来扩展window对象 . 我把它放在typings.d.ts中:
interface Window { my: any; }
现在,从控制台调用该函数非常简单:
my.namespace.publicFunc()
2 years ago
以下是一个解决方案 .
function callbackfunction(){
window.angularComponent.runThisFunctionFromOutside();
}
System.config({
transpiler: 'typescript',
typescriptOptions: { emitDecoratorMetadata: true },
packages: {'js/app': {defaultExtension: 'ts'}}
});
System.import('js/app/main')
.then(null, console.error.bind(console));
我的App.component.ts
import {Component NgZone} from 'angular2/core';
import {GameButtonsComponent} from './buttons/game-buttons.component';
@Component({
selector: 'my-app',
template: ' blblb'
})
export class AppComponent {
constructor(private _ngZone: NgZone){
window.angularComponent = {runThisFunctionFromOutside: this.runThisFunctionFromOutside, zone: _ngZone};
}
runThisFunctionFromOutside(){
console.log("run");
}
}
2 years ago
不使用全局变量的另一种方法是使用传递控制对象并将其属性绑定到要公开的变量和方法 .
export class MyComponentToControlFromOutside implements OnChanges {
@Input() // object to bind to internal methods
control: {
openDialog,
closeDialog
};
ngOnChanges() {
if (this.control) {
// bind control methods to internal methods
this.control.openDialog = this.internalOpenDialog.bind(this);
this.control.closeDialog = this.internalCloseDialog;
}
}
internalOpenDialog(): Observable {
// ...
}
internalCloseDialog(result: boolean) {
// ...
}
}
export class MyHostComponent {
controlObject= {};
}
Call open method
2 years ago
当使用fullCalendar库的回调'eventClick'时,我遇到了类似的情况,其回调是从角度区域外返回的,导致我的应用程序具有部分和不可靠的效果 . 我能够将区域方法和闭包引用组合到组件中,如下所示,以便引发输出事件 . 一旦我开始在zone.run()方法内执行事件,事件及其效果再次可以预测并通过角度变化检测来获取 . 希望这有助于某人 .
constructor(public zone: NgZone) { // code removed for clarity
}
ngOnInit() {
this.configureCalendar();
}
private configureCalendar() {
// FullCalendar settings
this.uiConfig = {
calendar: { // code removed for clarity
}
};
this.uiConfig.calendar.eventClick = this.onEventClick();
}
private onEventClick() {
const vm = this;
return function (event, element, view) {
vm.zone.run(() => {
vm.onSequenceSelected.emit(event.sequenceSource);
});
return false;
};
}
2 years ago
从控制台调用函数现在就像下面这样简单:my.namespace.publicFunc()
1) 如果我们尝试从不同的域访问我们组件的公共方法,您将陷入CORS问题(如果服务器和客户端代码都驻留在同一台机器中,则可以解决交叉原点问题) .
2) 如果您使用javascript从服务器调用此方法,则必须使用 window.opener.my.namespace.publicFunc() 而不是 window.my.namespace.publicFunc():
window.opener.my.namespace.publicFunc();