4

案子

我正在将 AngularJS(即 Angular 1.6)应用程序升级到 Angular(即 Angular 4.1.3)。我选择进行增量升级,因此目前 AngularJS 和 Angular 都已引导并运行。到目前为止一切都很好,但是:应该重写为 Angular 的 AngularJS 服务之一依赖于一个众所周知的服务$translate,该服务是第 3 方 AngularJS(阅读 Angular 1)模块pascalprecht.translate的一部分。换句话说,$translate注入的服务MyService应该成为 Angular(阅读 Angular 4)服务。

MyService(精简)看起来像这样:

import { Injectable } from '@angular/core';

@Injectable()
export class MyService {
    // Here comes the injection (how to do it?).
    constructor(private $translate: $translate) {

    }

    foo() {
        // Use the service
        this.$translate('HELLO_WORLD');
    }
}

它位于MyModule

import { NgModule } from '@angular/core';

import { MyService } from './my.service';

@NgModule({
    providers: [
        MyService
    ]
})
export class MyModule {
}

问题

现在,当我是第 3 方 AngularJS 模块的一部分时,如何注入$translate到Angular 模块中?MyServiceMyService$translate

如果 AngularJS 服务位于同一个模块中(或者至少该模块是我自己的解决方案的一部分),我知道如何将 AngularJS 服务注入到 Angular 服务中。官方文档中对此进行了解释。有没有办法处理第三方服务?我需要在MyModule的提供者中注册该服务吗?

import { NgModule } from '@angular/core';

import { MyService } from './my.service';

// How this line should look line then?
import { $translate } from 'node_modules/angular-translate/...';

@NgModule({
    providers: [
        MyService,
        $translate
    ]
})
export class MyModule {
}

还是我试图实现不可能?

4

1 回答 1

6

好吧,经过几个小时的努力,我终于找到了解决方案。这里是:

升级第三者服务

首先,遵循Angular 的官方指南,升级 3rd 方服务的提供者 - $translate. 像这样:

ajs-升级-providers.ts

import { InjectionToken } from '@angular/core';
import { downgradeInjectable } from '@angular/upgrade/static';

import 'angular-translate';

// Variable 'i' holds the standard AngularJS injector
export function $translateFactory(i: any) {
    return i.get('$translate');
};

// There is no class representing the good old $translate service so we have
// a non-class dependency. Therefore we use an InjectionToken (Angular 4) or
// OpaqueToken (Angular 2).
export let $translate = new InjectionToken('$translate');

// Finally create the upgraded provider
export const $translateProvider = { 
    provide: $translate,
    useFactory: $translateFactory,
    deps: ['$injector']
};

需要注意的一件事是,该$translate服务可能依赖于其他旧的 AngularJS 服务,例如(在我的情况下)$translateStaticFilesLoader$translateMessageFormatInterpolation. 如果这也是您的情况,请务必扩展上面的代码并为这些服务创建升级的提供程序(将它们保存在同一个文件中)。

确保import声明有效

angular-translate安装为节点模块,因此语句

import 'angular-translate';

如果您tsconfig.json设置为使用moduleResolution: "node".

然后,当然,您需要确保import即使在代码从 TypeScript 转换为 ES5(或您使用的任何目标)并被模块加载器(在我的情况下为 SystemJS)拾取之后,该语句仍能正常工作。

请注意,我们导入angular-translate脚本时没有从中获取任何内容,只是为了产生副作用。基本上,导入确保包含所需服务的脚本$translate被简单地执行并$translate为 AngularJS $injector 注册服务。

在 Angular 模块中注册升级后的提供者

现在确保新升级的$translate服务提供商在MyModule.

我的.module.ts

import { NgModule } from '@angular/core';

import { MyService } from './my.service';
import { $translateProvider } from './ajs-upgraded-providers';

@NgModule({
    providers: [
        MyService,
        $translateProvider
    ]
})
export class MyModule {
}

用它

最后,使用中的$translate服务MyService

我的.service.ts

import { Injectable, Inject } from '@angular/core';

import { $translate } from './ajs-upgraded-providers';

@Injectable()
export class MyService {
    // Notice the usage of InjectionToken
    constructor(@Inject($translate) private $translate: any) {
    }

    foo() {
        this.$translate('hello.world').then((translation: string) => {
            console.log(translation);
        });
    }
}
于 2017-06-16T13:40:30.797 回答