布莱恩F爱
向来自波特兰的谷歌开发者专yobet英雄联盟家学习Angular、Web技术和Node.js。
广告 ·ultimatecourses.com
使用Ultimate Courses以正确的方式学习Angular

角窗提供者

我的$window去哪了?没问题,可以使用这个提供商将窗口注入到Angular组件中。

为什么?

因为我们不想引用全局变量窗口对象直接在Angular组件中使用,因为我们的应用可能会在Angular Universal中使用,而且最好的做法是避免直接引用全局对象。虽然你可能没有使用Angular Universal的计划,但这让我们能够干净地注入浏览器的原生代码窗口对象转换为组件。

这有什么不同?

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

以下是一个我觉得不合适的解决方案:

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

快速查看一下,可以看出我们没有检查应用程序是否在浏览器的上下文中执行。此外,我们可能想要支持测试的上下文,在其中我们可能想要模拟窗口对象。

建议的解决方案

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

进口isPlatformBrowser“@angular /普通”进口ClassProviderFactoryProviderInjectionTokenPLATFORM_ID“@angular /核心”/*创建一个新的注入令牌,用于将窗口注入到组件中。*/出口常量窗口InjectionToken“WindowToken”/*定义抽象类以获取对全局窗口对象的引用。*/出口摘要WindowRef得到nativeWindow窗口|对象错误“未实现”。/*定义实现抽象类并返回本机窗口对象的类。*/出口BrowserWindowRef扩展WindowRef构造函数超级得到nativeWindow窗口|对象返回窗口/*创建一个返回本机窗口对象的工厂函数。*/出口函数windowFactorybrowserWindowRefBrowserWindowRefplatformId对象窗口|对象如果isPlatformBrowserplatformId返回browserWindowRefnativeWindow返回对象/*为使用BrowserWindowRef类的WindowRef令牌创建一个可注入的提供商。*/常量browserWindowProviderClassProvider提供WindowRefuseClassBrowserWindowRef/*创建一个可注入的提供商,使用windowFactory函数返回本机窗口对象。*/常量windowProviderFactoryProvider提供窗口useFactorywindowFactorydepsWindowRefPLATFORM_ID/*创建一个提供商数组。*/出口常量WINDOW_PROVIDERSbrowserWindowProviderwindowProvider

有几点需要注意:

  • 我有一个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感兴趣。我和我最好的朋友邦妮结婚了,我住在波特兰,我经常滑雪。