资讯专栏INFORMATION COLUMN

[译] 监听 Angular 启动过程

cjie / 1270人阅读

摘要:比如下面代码让初始化延迟秒执行当然你可以定义多个回调函数另外一个可以监听程序启动过程的地方就是使用方法这里你可以拿到被启动模块的对象引用,并通过该对象拿到和。

原文链接: Hooking into the Angular bootstrap process

Angular 提供了一些机制来监听框架初始化过程,本文主要探索如何使用这些机制。

APP_BOOTSTRAP_LISTENER

可以为 APP_BOOTSTRAP_LISTENER 令牌注册监听器来监听 Angular 启动过程,比如看看 Angular 源码 里是如何使用的:

private _loadComponent(componentRef: ComponentRef): void {
    this.attachView(componentRef.hostView);
    this.tick();
    this.components.push(componentRef);
    // Get the listeners lazily to prevent DI cycles.
    const listeners =
        this._injector.get(APP_BOOTSTRAP_LISTENER,[]).concat(this._bootstrapListeners);
    listeners.forEach((listener) => listener(componentRef));
  }

这个 _loadComponent() 函数会在初始化程序时被调用(译者注:这句可参考 application_ref.tsL245L281L463L492),通过观察这个函数不仅知道一个组件是如何被添加到程序里的(译者注:该方法第三行),还能知道对于每一个启动组件,Angular 都会执行使用 APP_BOOTSTRAP_LISTENER 令牌注册的监听器,并且把该启动组件对象作为参数传入监听器函数中(译者注:该函数第五行)。

这就意味着我们可以使用这些钩子来监听程序启动过程,执行自定义的初始化逻辑,比如 Router 模块监听启动过程,并执行了一些初始化过程

由于 Angular 把初始化后的启动组件对象作为参数传给回调函数,所以我们可以像这样拿到程序根组件对象 ComponentRef

import {APP_BOOTSTRAP_LISTENER, ...} from "@angular/core";
@NgModule({
  imports: [BrowserModule, ReactiveFormsModule, TasksModule],
  declarations: [AppComponent, BComponent, AComponent, SComponent, LiteralsComponent],
  providers: [{
    provide: APP_BOOTSTRAP_LISTENER, 
    multi: true, 
    useFactory: () => {
      return (component: ComponentRef) => {
        console.log(component.instance.title);
      }
    }
  }],
  bootstrap: [AppComponent]
})
export class AppModule {
}

在运行完上面代码后,我又查阅了官方文档,文档上是这样描述的(译者注:为清晰理解,该描述不翻译):

All callbacks provided via this token will be called for every component that is bootstrapped. Signature of the callback:
(componentRef: ComponentRef) => void
APP_INITIALIZER

Angular 也在程序(application)初始化前提供了钩子机制(译者注:Angular 框架有 platform 和 application 概念,Angular 在启动时会先实例化 platform,然后是 application,一个 platform 可以有多个 application,而 platform 可以有 platform-browser、platform-service-worker 或者 platform-server,因为 Angular 框架想做到跨平台,所以它得根据当前运行环境实例化特定的 platform。关于 platform 和 application 实例化过程也可参考 如何手动启动 Angular 程序),然后在初始化后就是变更检测和模板渲染过程。这段初始化过程步骤 是(译者注:下面源码是在 L53):

if (this.appInits) {
     for (let i = 0; i < this.appInits.length; i++) {
       const initResult = this.appInits[i]();
       if (isPromise(initResult)) {
         asyncInitPromises.push(initResult);
       }
     }
 }

所以,正如我们为 APP_BOOTSTRAP_LISTENER 令牌做的一样,这里也为 APP_INITIALIZER 注册回调函数。比如下面代码让 Angular 初始化延迟 5 秒执行:

{
  provide: APP_INITIALIZER,
  useFactory: () => {
    return () => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve();
        }, 5000);
      });
    }
  },
  multi: true
}

当然你可以定义多个 APP_INITIALIZER 回调函数:

{
  provide: APP_INITIALIZER,
  useFactory: () => {
    return () => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve();
        }, 5000);
      });
    }
  },
  multi: true
},
{
  provide: APP_INITIALIZER,
  useFactory: () => {
    return () => {
      return new Promise.resolve(2);
    }
  },
  multi: true
}
BootstrapModule

另外一个可以监听程序启动过程的地方就是使用 bootstrapModule 方法:

platform.bootstrapModule(AppModule).then((module) => {
  let applicationRef = module.injector.get(ApplicationRef);
  let rootComponentRef = applicationRef.components[0];
});

这里你可以拿到被启动模块的对象引用 NgModuleRef ,并通过该对象拿到 ApplicationRefComponentRef

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93930.html

相关文章

  • [] 如何使用 TypeScript 编写自定义 AngularJS 指令?

    摘要:在这篇文章中,我将告诉你如何用编写自定义指令。中的自定义指令让我们来创建一个只为任何的块,小部件或者人名在右边添加标题,子标题和文本的指令。另外,设置了指令的使用级别给元素和属性,分别使用和表示。 原文链接 : How to write custom AngularJS Directive using TypeScript?原文作者 : Siddharth Pandey译者 : 李林璞...

    CloudwiseAPM 评论0 收藏0
  • [] $digest 在 Angular 中重生

    摘要:但如果一个组件在生命周期钩子里改变父组件属性,却是可以的,因为这个钩子函数是在更新父组件属性变化之前调用的注即第步,在第步之前调用。 原文链接:Angular.js’ $digest is reborn in the newer version of Angular showImg(https://segmentfault.com/img/remote/146000001468785...

    incredible 评论0 收藏0
  • 】JavaScript 框架的探索与变迁(下)

    摘要:对此没有任何限制,它不关心这个。一种控制变化的办法是不可改变的,持久化的数据结构。总结检测变化时开发中的核心问题,而框架们以各种方式解决这个问题。因为组件内的变化是不被允许的。 AngularJS:脏检查 我不知道什么更新了,所以当更新的时候,我只能检查所有的东西。 AngularJS 类似于 Ember,当状态改变的时候,必须人工去处理。但不同的是,AngularJS 从不同的角度来...

    CollinPeng 评论0 收藏0
  • 】JavaScript 框架的探索与变迁(上)

    摘要:正文在年,框架的选择并不少。特别的,通过思考这些框架分别如何处理状态变化是很有用的。本文探索以下的数据绑定,的脏检查的虚拟以及它与不可变数据结构之间的联系。当状态产生变化时,只有真正需要更新的部分才会发生改变。 译者言 近几年可谓是 JavaScript 的大爆炸纪元,各种框架类库层出不穷,它们给前端带来一个又一个的新思想。从以前我们用的 jQuery 直接操作 DOM,到 Backb...

    Jaden 评论0 收藏0
  • Angular 4 简单入门笔记

    摘要:首先,我们需要在入口页面的中配置根路径然后创建一个路由模块路由配置在主模块中导入配置好的路由模块而在页面中需要一个容器去承载上面代码中的定义了用户点击后的路由跳转,定义该路由激活时的样式类。 刚实习的时候用过AngularJS,那时候真的是连原生JavaScript都不会写,依样画葫芦做了几个管理后台。然后突然换项目了,AngularJS就不写了,感觉前前后后接触了一年多的Angula...

    whlong 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<