Ответ 1
Injectable
Декоратор специфичен для TypeScript аромата Angular 2. Он позволяет неявно аннотировать конструктор класса для аннотаций типа DI через TypeScript. Он избыточен в TS и не используется в JS для вложенных зависимостей, которые аннотируются с помощью Inject
.
Angular 2 инъекции (классы и функции конструктора) должны быть аннотированы статическими свойствами annotations
и parameters
под капотом.
annotations
- это массив, содержащий new
ed декораторы для инъектируемого класса:
function SomeComponent(...) {}
SomeComponent.annotations = [new Componenent(...)];
parameters
- это массив, содержащий декораторы для параметров конструктора, каждый элемент представляет собой массив, содержащий список new
ed декораторов для соответствующего свойства конструктора (аналогично $inject
явно выраженной аннотации в Angular 1. х):
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) {}]
});
Angular 2/4 ES6 с System.import
An пример:
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));
Angular 2/4 ES5 с модулями UMD и ng
глобальный
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 };
// Class helper function that uses A1-flavoured inline array DI annotations
// and creates an annotated constructor
var Service = Class({
constructor: [[new Inject(CONSTANT_TOKEN)], function (constant) {
console.log('Service constructor', constant);
}]
});
// can also be
// function Service(constant) {};
// Service.parameters = [[new Inject(...)], ...];
// when not being `new`ed, Component is a chainable factory that has Class helper method
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);
}
]
});
// can also be
// function AppComponent(...) {};
// AppComponent.annotations = [new Component(...)];
// AppComponent.parameters = [[new Inject(...)], ...];
var AppModule = NgModule({
imports: [BrowserModule],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
.Class({ constructor: function () {} });
// can also be
// function AppModule() {};
// AppModule.annotations = [new NgModule(...)];
platformBrowserDynamic().bootstrapModule(AppModule);