【问题标题】:Accessing root Angular 2 injector instance globally全局访问根 Angular 2 注入器实例
【发布时间】:2016-07-27 02:27:43
【问题描述】:

如何全局访问根 Angular 2 注入器的实例(例如,从浏览器控制台)。

在 Angular 1 中它是angular.element(document).injector()

在测试和探索期间很有用,使用浏览器控制台获取注入器,然后访问不同组件、指令、服务等的实例。

【问题讨论】:

    标签: angular dependency-injection


    【解决方案1】:

    这是 Angular 9 的另一个版本。

    在不在生产节点中的 Angular 应用程序页面上打开 JavaScript 控制台。

    在页面上找到<app-root>

    root = document.querySelector("app-root");
    

    获取注射器。 ng() helper 是一个全局变量,如果应用程序处于开发模式,则可用:

    injector = ng.getInjector("app-root");
    

    Injector 将允许您通过其类名获取服务。不幸的是,我不知道 Angular 服务类是否或如何通过 window 命名空间获得。

    所以我们的下一个尝试是从页面上已经可见元素的组件中获取服务。

    appComponent = ng.getComponent(root)
    

    这样您就可以访问任何AppComponent 变量,例如您的应用可能具有“UserService”。

    appComponent.userService
    
    UserService {http: HttpService, userSubject: BehaviorSubject}
    

    现在你可以从控制台调用服务了:

    appComponent.userService.userSubject.value.userEmail
    
    mikko@capitalgram.com
    

    您还可以访问不是应用程序根的组件,并访问绑定到它们的服务。首先,我们需要导航到组件出现的页面。这将触发 UI 中的实际转换。

    await appComponent.router.navigate(["/another-page"])
    

    现在您可以通过标签名称获取任何可见组件:

    elem = document.querySelector("app-my-component")
    component = ng.getComponent(elem)
    

    你可以看到它的服务:

    MyComponent(envService, http, sanitizer);
    

    您可以在所有用户令牌、会话等就位的情况下戳它们:

    component.envService.getConfigValue()
    

    【讨论】:

      【解决方案2】:

      在 Angular v.4.x.x 中,根注入器位于 PlatformRef 上。你可以这样访问它:

      import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
      
      // create a platform    
      let platform = platformBrowserDynamic();
      
      // save reference to the global object
      window['rootInjector'] = platform.injector;
      
      // boostrap application
      platform.bootstrapModule(AppModule);
      

      或者在任何这样的组件中:

      export class AppComponent {
        constructor(platform: PlatformRef) {
            console.log(platform.injector);
      

      但是root 注入器非常没用。它主要包含编译器和平台特定的数据和帮助器:

      [
        "InjectionToken Platform ID",
        "PlatformRef_",
        "PlatformRef",
        "Reflector",
        "ReflectorReader",
        "TestabilityRegistry",
        "Console",
        "InjectionToken compilerOptions",
        "CompilerFactory",
        "InjectionToken Platform Initializer",
        "PlatformLocation",
        "InjectionToken DocumentToken",
        "InjectionToken Platform: browserDynamic",
        "InjectionToken Platform: coreDynamic",
        "InjectionToken Platform: core"
      ]
      

      您可能正在寻找AppModule 注射器,您可以像这样得到:

      platform.bootstrapModule(AppModule).then((module) => {
        window['rootInjector'] = module.injector;
      });
      

      您可以从中提取ApplicationRef 或root ComponentRef

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

      另外,如果 Angular 在开发模式下运行,您可以像这样获得 AppModule 或延迟加载的 NgModule 注入器:

      ng.probe($0).injector.view.root.ngModule
      

      【讨论】:

      • ng.probe($0).injector.view.root.ngModule 这样你就可以得到AppModule 或者延迟加载的NgModule 注入器
      • @yurzui,是的,但前提是enableProdMode()
      • 他问了It can be useful during testing and exploration,所以这会很有帮助:)
      • @yurzui,是的,谢谢,我会补充答案。我还发现了一种订阅应用程序引导过程的惊人方法:)。我会写一篇关于它的文章
      • @yurzui,感谢您提供的链接,很有趣。看来我对注射器的层次结构做对了:)
      【解决方案3】:

      您必须在启动应用程序后将其设置为服务:

      export var applicationInjector: Injector;
      
      bootstrap([AppComponent]).then((componentRef: ComponentRef) => {
        applicationInjector = componentRef.injector;
      });
      

      然后您可以将其导入应用程序的其他部分:

      import {applicationInjector} from './bootstrap';
      

      查看这个问题了解更多详情:

      编辑

      您可以将ApplicationRef 注入组件并通过它访问根注入器:

      @Component({
        (...)
      })
      export class SomeComponent {
        constructor(private app:ApplicationRef) {
          var rootInjector = app.injector;
        }
      }
      

      您需要利用依赖注入来获取它。

      【讨论】:

      • ComponentRef 的实例是否由 Angular 2 保存在任何地方并在全球范围内可用(例如 ng.core.rootComponent())?无论如何,手动保存它比 Angular 1 中可用的工作量更大,但仍然没问题。
      • 对于我不认为的根组件。话虽如此,您可以将ApplicationRef 注入您的组件并访问根注入器。无需手动保存 ;-) 我相应地更新了我的答案。
      • 在当前的 Angular (2.4.4) ApplicationRef 没有公共属性 injector;显然它是私有的。
      • @willydee,查看my answer 获取最新版本
      • @RPDeshaies,查看my answer 获取最新版本
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-23
      • 1970-01-01
      • 2023-03-25
      • 2020-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多