[译] 监听 Angular 启动历程

原文链接:
Hooking into the Angular bootstrap process

Angular 供应了一些机制来监听框架初始化历程,本文重要探究怎样运用这些机制。

APP_BOOTSTRAP_LISTENER

可认为 APP_BOOTSTRAP_LISTENER 令牌注册监听器来监听 Angular 启动历程,比方看看 Angular 源码 里是怎样运用的:

private _loadComponent(componentRef: ComponentRef<any>): 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<any>) => {
        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

    原文作者:lx1036
    原文地址: https://segmentfault.com/a/1190000014141518
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞