从iframe事件监听器触发时,角度UI更改不起作用

时间:2019-11-18 13:45:13

标签: angular iframe

我目前正在使用Angular 8应用程序,该应用程序充当iframe顶部的UI层,用于向用户显示增强的信息。 Angular应用程序将根据iframe中触发的事件显示不同的角度分量:

  • 显示一个工具提示(角度组件),用户在iframe中右键单击该提示
  • 当用户单击iframe的特定部分时,更改组件的UI属性
  • ...

我当前面临的问题是Angular显示/更新UI中的更改,但是在30秒后,有时甚至忽略了UI更新,并且更改在UI中不可见。

但是,如果我只运行确切的代码,但使用Angular按钮click事件作为事件的触发,一切就很好了。

以下是有关如何创建来自iframe的事件的侦听器的代码段:

this.iframe = document.getElementById('iframe') as any;
let canv = this.iframe.contentDocument.getElementById('canv');
canv.addEventListener('contextmenu', (event) => this.onContextMenuEvent(event))

作为onContextMenuEvent代码的一部分,我只是计算一些用于定位工具提示的坐标,然后使用布尔标志启用组件。以下是在app.component.html内部引用工具提示组件的方式:

<app-tooltip *ngIf="isTooltipShown"
  [offsetX]="tooltipOffsetX"
  [offsetY]="tooltipOffsetY"
</app-tooltip>

正如我指出的,如果onContextMenuEvent的代码是从Angular UI元素触发的,则不会发生此问题。

作为提示,问题出现时的堆栈跟踪非常短,只有两行:

eevOnContextMenuEvent (app.component.ts:597)
(anonymous)(app.component.ts:394)

而另一种情况相当长,中间有很多Angular调用:

fakeTooltip (app.component.ts:566)
(anonymous) (app.component.ngfactory.js.pre-build-optimizer.js:68)
handleEvent (core.js.pre-build-optimizer.js:43993)
callWithDebugContext (core.js.pre-build-optimizer.js:45632)
debugHandleEvent (core.js.pre-build-optimizer.js:45247)
dispatchEvent (core.js.pre-build-optimizer.js:29804)
(anonymous) (core.js.pre-build-optimizer.js:31837)
schedulerFn (core.js.pre-build-optimizer.js:35379)
__tryOrUnsub (Subscriber.js.pre-build-optimizer.js:185)
next (Subscriber.js.pre-build-optimizer.js:124)
_next (Subscriber.js.pre-build-optimizer.js:72)
next (Subscriber.js.pre-build-optimizer.js:49)
next (Subject.js.pre-build-optimizer.js:39)
emit (core.js.pre-build-optimizer.js:35298)
resetSchematics (hideable-panel.component.ts:230)
(anonymous) (hideable-panel.component.ngfactory.js.pre-build-optimizer.js:50)
handleEvent (core.js.pre-build-optimizer.js:43993)
callWithDebugContext (core.js.pre-build-optimizer.js:45632)
debugHandleEvent (core.js.pre-build-optimizer.js:45247)
dispatchEvent (core.js.pre-build-optimizer.js:29804)
(anonymous) (core.js.pre-build-optimizer.js:42925)
(anonymous) (platform-browser.js.pre-build-optimizer.js:2668)
invokeTask (zone-evergreen.js.pre-build-optimizer.js:391)
onInvokeTask (core.js.pre-build-optimizer.js:39680)
invokeTask (zone-evergreen.js.pre-build-optimizer.js:390)
runTask (zone-evergreen.js.pre-build-optimizer.js:168)
invokeTask (zone-evergreen.js.pre-build-optimizer.js:465)
invokeTask (zone-evergreen.js.pre-build-optimizer.js:1603)
globalZoneAwareCallback (zone-evergreen.js.pre-build-optimizer.js:1629)

关于如何解决此问题的任何提示?

谢谢。

编辑1 : 根据评论的要求,我分享了onContextMenuEvent的部分代码(很遗憾,我无法分享实际的代码):

onContextMenuEvent(mouseEvent: any): void {
   var param = this.getEventParameters(mouseEvent);
   this.tooltipOffsetX = param.x;
   this.tooltipOffsetY = param.y;
...
   this.isTooltipShown = true;
}

另一个提示是,工具提示组件上的方法ngOnChanges不会立即被调用,而是会在30秒钟后(不是恒定的)被调用。

1 个答案:

答案 0 :(得分:2)

Angular可能会丢失其“区域”。

尝试使用

将其导入构造器中的区域
constructor(
     private zone: NgZone
) { ... }

并在区域内运行onContextMenuEvent

onContextMenuEvent(mouseEvent: any): void {
   this.zone.run(() => {
         var param = this.getEventParameters(mouseEvent);
         this.tooltipOffsetX = param.x;
         this.tooltipOffsetY = param.y;
         ...
         this.isTooltipShown = true;
   })
}

可能足以将this.isTooltipShown = true;包裹在区域内