普通 Javascript 作为 Angular 2 服务

Plain Javascript as Angular 2 service

我需要在 Angular 2 组件中添加托管的第三方 JavaScript 文件。每当关联的第三方供应商专有系统发生更改时,此文件都会更新,因此我不能简单地下载一个副本,将其包含在本地,然后将其导入到项目中。

通常我会将此文件包含在脚本标记的顶层,然后只需使用 declare <windowvar>: any 即可访问它。但是在这种情况下,由于组件本身正在尝试加载脚本,我无法声明 window 变量,因为它在组件加载时不存在于 window 对象上,这会生成一个错误。

我可以通过手动添加脚本标签来加载脚本,这很有效,但是我需要访问它创建的 window 变量才能正确使用它。而且我不能简单地使用间隔来查找它,因为打字稿会引发 <windowvariable> does not exist on object window.

有什么方法可以 1) 在组件中加载托管的 JavaScript 文件,以及 2) 访问由加载的 JavaScript 文件创建的 window 变量?

更新 1:根据评论,之前的解决方案对您没有帮助。

你可以在 Angular2 中使用 OpaqueToken

1。创建一个用于在单独的 ts 文件中查找实例的令牌。

import { OpaqueToken } from '@angular/core'

export let name_of_The_Token = new OpaqueToken('name_Of_The_Window_Object');

2. 在你的App.module中,你需要导入并声明一个变量 这是你的 window 对象的名称,它使令牌成为一个 angular2 服务,这样你就可以在你的组件中使用 javascript 文件中的属性和方法。

import { name_of_The_Token } from '/* file_Path */';
declare let name_Of_The_Window_Object : any;  //below your import statements

第 3 步:将其注入 到您模块的提供程序数组。

{ provide : name_of_The_Token , useValue : name_Of_The_Window_Object }

在组件中使用此令牌的指南

  1. 像任何其他服务一样导入令牌,并从 angular-core

    导入 @Inject
     import { name_of_The_Token } from '/* file_Path */';
     import { Inject } from '@angular/core';
    
  2. 在组件的构造函数中

     constructor(@Inject( name_of_The_Token ) private _serviceObject : any )       
    
  3. 您可以在组件中的任何地方使用 javascript 文件的变量和方法作为

     this._serviceObject.method1()
     this._serviceObject.variable1
     .....
    

注意:一个缺点是您将无法获得智能感知

克服它: 如果您正在寻找智能感知,您需要 将方法和变量包装在一个接口 中,并在您的令牌的类型**(而不是任何)** 中使用它作为

export interface myCustom {
      method1(args): return_Type;
      method2(args): void;
      .....
   }
ToasterService

LIVE DEMO

实际上,您正在尝试从 CDN 获取 "global module" javascript 库。 (我假设第 3 方库不是 CommonJS、AMD、UMD 或其他模块格式,因为它是通过唯一的全局变量访问的。)

那么第一个问题就是对应的.d.ts文件在哪里?它包含通知 Typescript 库的 'shape' 的名称和接口,以及声明将存在的全局变量。如果您的第 3 方不提供它,您需要自己编写。它不仅包含全局变量的声明,如

declare var theGlobalVarInQuestion: IInterfaceOfStuffInsideLibrary;

还有所述接口的声明,及其属性和类型,一直向下。像这样:https://github.com/catamphetamine/libphonenumber-js/blob/master/index.d.ts

您可以将 .d.ts 文件包含在 /node_modules/@types/nameOfSaidLibrary 中,但您需要将其检查到您的源代码库中(可能需要 .gitignore 体操),尤其是因为 npm prune 会删除它。或者,如果您将它放在其他地方,请修改 tsconfig.json typeroots 属性 以在除了通常的 /node_modules/@types/ 文件夹之外的两个地方查找。

需要说明的是,.d.ts 文件不会(也不应该)实际创建变量;它只是声明它会在那里,这样 Typescript 编译器就不会抱怨。它是否在运行时存在取决于您加载 js 的方式。

如果你没有通过 index.html 中的脚本标签加载它,那么消费组件中的 Typescript import 语句可以这样做(给定正确的 SystemJS 配置或任何你正在使用)或者消费组件可以动态创建新的脚本标签并将其附加到 index.html。只要确保您的模块加载器没有尝试下载并在构建时立即将其与应用程序的其余部分捆绑在一起即可。听起来您希望每次在运行时都重新下载 lib。