Injectable
装饰器是 Angular 2 中 TypeScript 版本特有的。它通过 TypeScript 类型注解隐式地为 DI 注释类构造函数。对于已使用 Inject
注释的注入依赖项,它在 TS 中是冗余且在 JS 中不需要。
Angular 2 可注入对象(类和构造函数)应该在底层使用 annotations
和 parameters
静态属性进行注释。
annotations
是一个包含可注入类的 new
ed 装饰器的数组:
function SomeComponent(...) {}
SomeComponent.annotations = [new Componenent(...)];
parameters
是一个数组,其中包含构造函数参数的装饰器,每个元素是一个数组,其中包含相应构造函数属性的新装饰器列表(类似于 Angular 1.x 中的 $inject
属性显式注释):
function Service(someService, anotherService) {}
Service.parameters = [
[new Inject(SomeService)],
[new Inject(AnotherService), new Optional, new SkipSelf]
];
所有类装饰器都是从
TypeDecorator
扩展而来,这意味着它们可以被调用为函数。在这种情况下,使用所谓的DSL语法,允许将装饰器与
Class
助手函数链接起来:
var SomeComponent = Componenent(...).Class(...);
Class
也可单独使用,它通过给定的定义对象构造一个新类,并允许对constructor
方法进行注释(类似于Angular 1.x中的内联数组显式注释):
var SomeService = Class({
constructor: [[new Inject(SomeService)], function (someService) {}]
});
Class
helper在最新的框架版本中已经被弃用,应该使用ES5中的原始函数或第三方类帮助程序进行替换。装饰器支持直接链接类函数,Componenent(...)(ComponentClass)
.
使用System.import
的Angular 2/4 ES6
一个示例:
Promise.all([
System.import('@angular/core'),
System.import('@angular/platform-browser'),
System.import('@angular/platform-browser-dynamic')
])
.then(([
{Component, Inject, Injectable, Optional, NgModule, OpaqueToken},
{BrowserModule},
{platformBrowserDynamic}
]) => {
const CONSTANT = { value: 'constant' };
const CONSTANT_TOKEN = new OpaqueToken;
const CONSTANT_PROVIDER = { provide: CONSTANT_TOKEN, useValue: CONSTANT };
class Service {
constructor(constant) {}
}
Service.parameters = [[new Inject(CONSTANT_TOKEN)]];
class AppComponent {
constructor(service, constant) {}
}
AppComponent.annotations = [new Component({
selector: 'app',
template: '...',
providers: [Service, CONSTANT_PROVIDER]
})];
AppComponent.parameters = [[new Inject(Service)], [new Inject(CONSTANT_TOKEN)]];
class AppModule {}
AppModule.annotations = [new NgModule({
imports: [BrowserModule],
declarations: [AppComponent],
bootstrap: [AppComponent]
})];
platformBrowserDynamic().bootstrapModule(AppModule);
})
.catch((err) => console.error(err));
使用UMD模块和ng
全局的Angular 2/4 ES5
一个示例:
var Class = ng.core.Class;
var Component = ng.core.Component;
var Inject = ng.core.Inject;
var Injectable = ng.core.Injectable;
var NgModule = ng.core.NgModule;
var OpaqueToken = ng.core.OpaqueToken;
var BrowserModule = ng.platformBrowser.BrowserModule;
var platformBrowserDynamic = ng.platformBrowserDynamic.platformBrowserDynamic;
var CONSTANT = { value: 'constant' };
var CONSTANT_TOKEN = new OpaqueToken;
var CONSTANT_PROVIDER = { provide: CONSTANT_TOKEN, useValue: CONSTANT };
var Service = Class({
constructor: [[new Inject(CONSTANT_TOKEN)], function (constant) {
console.log('Service constructor', constant);
}]
});
var AppComponent = Component({
selector: 'app',
template: '...',
providers: [Service, CONSTANT_PROVIDER]
})
.Class({
constructor: [
[new Inject(Service)],
[new Inject(CONSTANT_TOKEN)],
function (service, constant) {
console.log('AppComponent constructor', service, constant);
}
]
});
var AppModule = NgModule({
imports: [BrowserModule],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
.Class({ constructor: function () {} });
platformBrowserDynamic().bootstrapModule(AppModule);
Injectable
的事情。它似乎使一个类能够通过TS类型注释使用隐式注入,并且对于仅依赖于Inject
(如在JS中)的可注入对象是不必要的。我想我稍后会发布自己的答案。 - Estus Flask