Angular 5:如何使用 ES6/ES5 注入路由器服务(不使用 Typescript)

Angular 5 : How to inject Router service with ES6/ES5 (without Typescript)

TL;DR

我想用 ES6/ES5 将 Angular 路由器服务注入到一个组件中(是的,没有 Typescript :p)。


大家好,

我最近为 javascript 创建了一个 Angular 5 代理,因为我不想使用 Typescript。

我的图书馆在 github 上可用:https://github.com/kevinbalicot/angular-js-proxy.

当你想创建你的组件、你的可注入服务和你的 NgModule 时,它​​是有效的。

在 jsFiddle 上查看这个例子 https://jsfiddle.net/kevinbalicot/nynzceb1/

// ng variable contains { compiler, common, core, router, platformBrowserDynamic, platformBrowser } from Angular 5 library

class Service {
    constructor() {}

    toUpperCase(string) {
        return String(string).toUpperCase();
    }
}

// Like @Injectable
Injectable({})(Service);

class HomeComponent {
    constructor(service) {
        this.message = service.toUpperCase('hello');
    }
}

// Like @Component
Component({
      selector: 'home-component',
      providers: [Service],
      template: `
            <h1>{{ message }}</h1>
        `
})(HomeComponent);

class Module {
    constructor() {}
}

// Like @NgModule
NgModule({
      imports: [ng.platformBrowser.BrowserModule],
      declarations: [HomeComponent],
      providers: [],
      bootstrap: [HomeComponent]
})(Module);

ng.platformBrowserDynamic.platformBrowserDynamic().bootstrapModule(Module);

您将能够创建可注入服务并将其注入到您的组件中。

问题

例如,当我想注入 Angular 服务(例如路由器)时,我收到 Angular 注入器错误

Error: Can't resolve all parameters for Router: (?, ?, ?, ?, ?, ?, ?, ?).

jsFiddle 上的演示 https://jsfiddle.net/kevinbalicot/nynzceb1/4/

// ng variable contains { compiler, common, core, router, platformBrowserDynamic, platformBrowser } from Angular 5 library

class Service {
    constructor() {}

    toUpperCase(string) {
        return String(string).toUpperCase();
    }
}

// Like @Injectable
Injectable({})(Service);

class HomeComponent {
    constructor(service, router) {
        this.message = service.toUpperCase('hello');
    }
}

// Like @Component
Component({
      selector: 'home-component',
      providers: [Service, ng.router.Router],
      template: `
            <h1>{{ message }}</h1>
        `
})(HomeComponent);

class Module {
    constructor() {}
}

// Like @NgModule
NgModule({
      imports: [
            ng.platformBrowser.BrowserModule,
            ng.router.RouterModule
      ],
      declarations: [HomeComponent],
      providers: [],
      bootstrap: [HomeComponent]
})(Module);

ng.platformBrowserDynamic.platformBrowserDynamic().bootstrapModule(Module);

我是否必须以不同于自定义可注入服务的方式注入 Angular 服务? (我的代码在这里:https://github.com/kevinbalicot/angular-js-proxy/blob/master/src/index.js#L51)。

function NgModule(metadata = {}) {
    return function decorator(target) {
        target.annotations = [new core.NgModule(metadata)];
        target.parameters = [];

        if (!!metadata.providers && Array.isArray(metadata.providers)) {
            metadata.providers.forEach(provider => {
                if (!provider.useValue && !provider.useClass) {
                    // Like Service class on example
                    target.parameters.push([new core.Inject(provider)]);
                } else {
                    // Like { provide: LOCALE_ID, useValue: 'en-EN' } provider
                    target.parameters.push([new core.Inject(provider.provide), provider.useValue || provider.useClass]);
                }
            });
        }

        return target;
    }
}

感谢阅读,欢迎任何想法。


编辑 我的问题与

不同

因为版本 4 和版本 5 之间的依赖注入不同 (https://github.com/angular/angular/blob/master/CHANGELOG.md#breaking-changes)

Injectable 仅适用于 TypeScript,它使用发出的参数类型为 DI 注释可注入的 class。

类在ES5和ES6中要注解为static parameter 属性,如:

class HomeComponent {
    constructor(service, router) {
        this.message = service.toUpperCase('hello');
    }
}
HomeComponent.parameters = [
  [new ng.core.Inject(Service)],
  [new ng.core.Inject(ng.router.Route)]
];

这个例子的一个问题是 Router 应该是全局提供者,它不应该在组件 providers 中定义。这里是 an example.

对于像Router这样的Angular服务,不应该定义在component providers中,因为Route应该是global provider。

此处示例https://jsfiddle.net/kevinbalicot/nynzceb1/6/

// ng variable contains { compiler, common, core, router, platformBrowserDynamic, platformBrowser } from Angular 5 library

class DefaultComponent {
    constructor(route) {
        this.route = route;
    }
}

// You can override class parameters for inject Angular service
DefaultComponent.parameters = [[new ng.core.Inject(ng.router.ActivatedRoute)]];

// Like @Component
Component({
      template: `
            <h2>Route : {{ route }}</h2>
        `
})(DefaultComponent);

感谢@estus