布莱恩F爱
从俄勒冈州波特兰的一位专注yobet英雄联盟于Angular、Web技术和Node.js的谷歌开发专家那里学习。
广告 ·ultimatecourses.com
以正确的方式学习Angular的终极课程

角窗提供者

我的钱窗口去哪了?没问题,用这个提供商把窗口注入到你的Angular组件中。

为什么?

因为我们不想引用全局变量窗口因为我们的应用可能会在Angular Universal中使用,所以最好的做法是避免直接引用全局对象。虽然你可能不打算使用Angular Universal,但这让我们能够干净地注入浏览器的native窗口对象转换为组件。

这有什么不同?

虽然已经有很多解决方案提出了间接访问窗口对象,我发现它们中的许多实际上并不执行任何条件验证,而我们的Angular应用是在浏览器的上下文中执行的窗口对象。

以下是一个我认为不合适的解决方案:

进口{可注射的}“@angular /核心”;函数getWindow():任何{返回窗口;}@可注射的()出口WindowRefService{得到nativeWindow():任何{返回getWindow();}}

快速查看一下,就会发现我们不是在检查应用程序是否在浏览器的上下文中执行。此外,我们可能希望支持测试的上下文,其中我们可能希望模拟一些属性或方法窗口对象。

建议的解决方案

下面是一个建议的解决方案,用于创建可扩展的方法注入窗口放到Angular组件中。我把这个代入src / app /核心/服务/ window.service.ts申请文件:

进口{isPlatformBrowser}“@angular /普通”;进口{ClassProvider,FactoryProvider,InjectionToken,PLATFORM_ID}“@angular /核心”;/*创建一个新的注入令牌,用于将窗口注入到组件中。* /出口常量窗口=InjectionToken(“WindowToken”);/*定义抽象类获取全局窗口对象的引用。* /出口摘要WindowRef{得到nativeWindow():窗口|对象{错误(“未实现”。);}}/*定义实现抽象类并返回本机窗口对象的类。* /出口BrowserWindowRef扩展WindowRef{构造函数(){超级();}得到nativeWindow():窗口|对象{返回窗口;}}/*创建一个返回本机窗口对象的工厂函数。* /出口函数windowFactory(browserWindowRef:BrowserWindowRef,platformId:对象):窗口|对象{如果(isPlatformBrowser(platformId)){返回browserWindowRefnativeWindow;}返回对象();}/*为使用BrowserWindowRef类的WindowRef令牌创建一个可注入的提供者。* /常量browserWindowProvider:ClassProvider={提供:WindowRef,useClass:BrowserWindowRef};/*创建一个可注入的提供程序,使用windowFactory函数返回本机窗口对象。* /常量windowProvider:FactoryProvider={提供:窗口,useFactory:windowFactory,deps:(WindowRef,PLATFORM_ID]};/*创建一个提供程序数组。* /出口常量WINDOW_PROVIDERS=(browserWindowProvider,windowProvider];

以下几点需要注意:

  • 我有一个InjectionToken被声明为窗口这是出口。我们将使用这个注入窗口对象到组件中。
  • 我定义了一个抽象类WindowRef对象的访问器nativeWindow财产。
  • 然后定义BrowserWindowRef类,该类扩展抽象类,实现nativeWindow属性返回全局可用的窗口对象。
  • windowFactory ()方法确定应用程序是否在浏览器的上下文中使用isPlatformBrowser ()函数。现在,如果应用程序没有在浏览器的上下文中执行,那么我只需返回一个new对象。这部分是可扩展的,因为您可以在另一个上下文中返回模拟对象。函数的一个实例BrowserWindowRefplatformId对象。类中指定了这些依赖项windowProvider
  • browserWindowProvider是一个ClassProvider的实例BrowserWindowRef使用WindowRef注入令牌。
  • windowProvider是一个FactoryProvider使用windowFactory返回窗口对象(或空对象)时窗口使用注入令牌。
  • 最后,我们声明一个被调用的提供程序数组WINDOW_PROVIDERS

要使用它,我们需要添加WINDOW_PROVIDERS对我们的app.module.ts模块装饰的供应商数组:

@NgModule({声明:(AppComponent,],进口:(BrowserModule],供应商:(WINDOW_PROVIDERS],引导:(AppComponent]})出口AppModule{}

你也可能有CoreModule(可能有不同的名称)是一个模块,包含所有的服务,拦截器,模型等,可用于您的应用程序。如果是这种情况,只需导入WINDOW_PROVIDERS在该模块中,然后将其导入到AppModule

然后,我们可以使用窗口注入令牌注入窗口我们的组件:

进口{窗口}“. . /核心/服务/ window.service”;出口IndexComponent{构造函数(@注入(窗口)私人窗口:窗口){控制台日志(窗口);}}

下面是一个显示window.navigator.userAgent字符串:

布莱恩F爱

嗨,我是布莱恩。我对TypeScript, Angular和Node.js感兴趣。我和我最好的朋友邦妮结婚了,我住在波特兰,我经常滑雪。