Angular 2 App Component ngOnInit 在使用 iframe 时调用了两次

Posted

技术标签:

【中文标题】Angular 2 App Component ngOnInit 在使用 iframe 时调用了两次【英文标题】:Angular 2 App Component ngOnInit called twice when using iframe 【发布时间】:2017-04-08 14:05:14 【问题描述】:

我正在开发一个 Angular 2 应用程序,该应用程序将通过 iframe 在其他网站上交付。在测试时,我注意到当我加载应用程序时,App Component ngOnInit() 函数被调用了两次。

我觉得这很奇怪,因为当我“单独”测试应用程序时,即不是 iframe,应用程序组件 ngOnInit() 只被调用一次。

根据this answer,这可能是由于子组件中的错误而发生的。但就我而言,“正常”运行应用程序时我没有遇到问题。

示例代码:

import  Component, OnInit  from '@angular/core';

@Component(
    selector: 'my-app',
    template: `<h1>My App!</h1>`
)
export class AppComponent implements OnInit 
    constructor() 
        console.log('App Component constructor()');
    

    ngOnInit() 
        console.log('App Component ngOnInit()');
    

Iframe 测试:

<!DOCTYPE html>
<html>
    <body>
        <h1>My Test Page</h1>
        <!-- iframe accessing my-app component -->
        <iframe id="test-iframe" src="/#/"  ></iframe>
   </body>
</html>

我仅使用 AppComponent 测试了应用程序,以确保没有子组件导致任何问题。

控制台输出:

【问题讨论】:

我认为这种行为很正常,因为 iframe 行为像浏览器和重新创建文档,因此您的组件再次重​​新初始化。 好的,但是如果你有一个带有一个 iframe 的页面显示 Angular 应用程序,就像我上面显示的 iframe 测试一样,AppComponent 不应该被触发一次吗?如果我在两个地方显示 my-app 组件,我会理解的。 您是否使用像 这样的 abs 路径测试了 src ? 在测试中我有 Angular 应用程序和测试页面在同一个站点上,只是不同的页面。因此,是否使用绝对路径访问 iframe 并没有什么区别。我只是为了以防万一,但它仍然导致 ngOnInit() 被调用两次。 我在 apache 上对其进行了测试,并将其发布在子域 angular2.alisch.me/iframe.htmlngOnInit 上,并且构造函数只运行一次。我认为可能是iis有问题。来源:angular2.alisch.me/ng2.zip | =>解压缩=>npm install =>npm run build:prod 【参考方案1】:

根据我的理解,最有可能的问题是,由于在 @Component 完成加载后调用了 ngOnInit() 方法,因此 iframe 元素的加载在 ngOnInit() 生命周期完成后立即开始,导致 iframe src值为空。

这意味着由于 iframe 在调用 ngOnInit() 后加载自身,因此来自组件的任何src 值对它来说都是陌生的,因此 null

注意:iframe就像一个外部浏览器注入到DOM中,所以它有自己的加载时间。

所以我建议将constructor() 用于此类事情,因为它总是在类被实例化时调用。

【讨论】:

以上是关于Angular 2 App Component ngOnInit 在使用 iframe 时调用了两次的主要内容,如果未能解决你的问题,请参考以下文章

子视图初始化后 App.component.ts 中的 Angular 8+ Fire 事件

无法在 app.component Ionic / Angular 中获取数据

每个 http 请求上的 Angular 2 加载器

在 angular4 的 app.component.ts 文件中使用外部库变量

Angular 2单选按钮验证

Angular 2背景图像未呈现