在 Angular 组件中放置 JavaScript 监听函数的最佳位置是啥?
Posted
技术标签:
【中文标题】在 Angular 组件中放置 JavaScript 监听函数的最佳位置是啥?【英文标题】:What is the best place to put a JavaScript listening function in Angular component?在 Angular 组件中放置 JavaScript 监听函数的最佳位置是什么? 【发布时间】:2018-07-08 21:50:39 【问题描述】:TL;DR:
我在 iFrame
内的 Angular 5 应用程序中渲染 BioDigital HumanAPI 解剖模型。我使用以下方法实例化 API 对象:
this.human = new HumanAPI(iFrameSrc);
有一个 API 函数 human.on(...)
可用于从 iFrame
中注册点击事件(例如从模型中选取对象等)。我需要这个功能才能随时收听事件。我进行对象实例化并将这个函数放在ngOnInit()
中并且它可以工作,但是当我更改iFrame
的源以呈现不同的模型时,这个函数停止工作。我应该把这个监听函数放在哪里,以便它的逻辑始终可用?
加长版:
我正在使用 BioDigital HumanAPI 开发一个 Angular 应用程序。这里的基本思想是 HumanAPI 提供了几个解剖模型,可以使用iFrame
(例如here)在网络应用程序中呈现这些模型。这个iFrame
的src
是一个链接,类似于:
https://human.biodigital.com/widget?m=congestive_heart_failure
因为我希望我的 Angular 应用程序的用户能够查看多个这样的模型,所以我有一个这些 URL 的列表,并根据用户的选择,我使用一个函数更新 iFrame
的 src
updateFrameSrc
代码如下:
iframeSrc: SafeUrl;
this.iframeSrc = this.sanitizer.bypassSecurityTrustResourceUrl(newUrl);
最后(问题来了,请和我在一起),为了在iFrame
本身内操作和注册不同的点击事件和用户与模型的交互,我们制作了一个这样的 HumanAPI 对象:
this.human = new HumanAPI(iFrameID);
这让我们可以使用像human.on('scene.picked')
这样的API 事件监听器函数来注册和保存点击事件(如我上面引用的示例所示)。所有这些都运行良好。
问题是,由于我在ngOnInit()
函数中初始化了human
对象并将human.on('scene.picked')
函数放在那里,所以在iFrame
源更改后我无法注册点击事件。据我了解,ngOnInit()
仅在组件首次初始化时调用一次,所以 可能 更新iFrame
源后human.on
的监听逻辑不可用?我尝试将逻辑放在不同的生命周期挂钩中,但它不起作用。
我目前的解决方法是在更新 iFrame
源后重新调用 ngOnInit()
函数,它就是这样工作的,但我认为这违反了标准生命周期管理实践。
我的问题是:
是否可以从组件逻辑中重新调用ngOnInit()
函数?
如果不是,我应该在哪里放置一个 javascript API 函数,该函数始终监听来自 iFrame
的点击事件,即使在 iFrame
的源已更改之后?
【问题讨论】:
为什么你不能把你需要的两行从 ngOnInit() 移到一个单独的函数中,并在 ngOnInit 和你的 updateFrameSrc 函数中调用该函数? @AbrahamAl-Dabbagh 好的,这毕竟是答案。我曾尝试过这种方式,但在更新iFrame
源后忘记再次初始化human
对象。请将此添加为答案,以便我接受!
【参考方案1】:
如果您正在寻找接近实时的数据,您会希望这发生在 NgOnChanges 生命周期挂钩中。请注意,这很昂贵。
如果可以接受稍微少一点的“接近实时”,我建议在组件初始化 NgOnInit 时连接一个快速延迟主题 Observable.Interval(500)
(同样,但稍微便宜一些)。
请不要通过重新调用 ngOnInit 来绕过钩子。
如果您还有其他问题,请告诉我。
【讨论】:
我尝试使用ngOnChanges()
进行此操作,但正如您所说,这对我的应用程序来说非常昂贵。问题是,只要我不更改 iFrame
源并且不使用延迟或某种强制侦听事件(例如在每个 mouseDown 事件上)。召回 ngOnInit()
也可以,所以我想可能也存在一些更便宜的解决方法。
我刚刚通过在 NgOnInit 中引导一个周期性任务 (Observable.Interval) 做了类似的事情。它会起作用,并且对于大多数用例,DOM 将呈现足够快的速度,以至于操作员/用户不会感觉到将其放入 ngOnChanges 中的任何延迟。请不要回忆 ngOnInit。它会导致可能不会立即显现出来的问题。【参考方案2】:
正如之前评论中所建议的,您可以将ngOnInit()
中的代码移动到一个单独的函数中,然后从ngOnInit()
以及您的更新函数中调用该函数。
在更新iFrame
源时,不要忘记在该函数中重新初始化HumanAPI
的human
对象。
应避免重新调用ngOnInit()
,因为它会绕过@iHazCode 提到的可接受的生命周期挂钩功能。
【讨论】:
以上是关于在 Angular 组件中放置 JavaScript 监听函数的最佳位置是啥?的主要内容,如果未能解决你的问题,请参考以下文章
不能在 Angular 构造函数或 OnInit 中放置断点
如何在 Angular Material 的对话框中放置图像?
如何在我的 ag-grid 单元格中放置一个 react jsx 组件