ES5 和 ES6 中的 Angular 2 依赖注入 [英] Angular 2 dependency injection in ES5 and ES6
问题描述
这是一个基本的 TypeScript/ES.next 示例,它使用装饰器进行 DI 并遵循框架手册建议的语法:
Here is a basic TypeScript/ES.next example that uses decorators for DI and follows the syntax suggested by the framework manual:
import {Component, Inject, Injectable, NgModule, OpaqueToken} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
const CONSTANT = { value: 'constant' };
const CONSTANT_TOKEN = new OpaqueToken;
const CONSTANT_PROVIDER = { provide: CONSTANT_TOKEN, useValue: CONSTANT };
@Injectable()
class Service {
constructor(@Inject(CONSTANT_TOKEN) constant) {
console.log('Service constructor', constant);
}
}
@Component({
selector: 'app',
template: '...',
providers: [Service, CONSTANT_PROVIDER]
})
class AppComponent {
constructor(@Inject(Service) service: Service, @Inject(CONSTANT_TOKEN) constant) {
console.log('AppComponent constructor', service, constant);
}
}
@NgModule({
imports: [BrowserModule],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
class AppModule {}
platformBrowserDynamic().bootstrapModule(AppModule);
在 ES5 中会如何编写?
How would it be written in in ES5?
如何在 未转译 ES6/ES2015 中完成同样的事情?
How would the same thing be done in untranspiled ES6/ES2015?
在这些情况下如何翻译 Injectable
和 Inject
装饰器?
How are Injectable
and Inject
decorators translated in these cases?
该问题特别适用于具有类但可能使用 require
或 System.import
而不是 ES6 导入的实际 ES6 浏览器实现.
The question particularly applies to real-world ES6 browser implementations that have classes but may use require
or System.import
instead of ES6 imports.
推荐答案
Injectable
装饰器特定于 Angular 2 的 TypeScript 风格.它使类构造函数能够通过 TypeScript 类型注释为 DI 隐式注释.对于使用 Inject
注释的注入依赖项,它在 TS 中是多余的,在 JS 中不需要.
Injectable
decorator is specific to TypeScript flavour of Angular 2. It enables a class constructor to be implicitly annotated for DI through TypeScript type annotations. It is redundant in TS and unneeded in JS for injected dependencies that are annotated with Inject
.
Angular 2 可注入对象(类和构造函数)应该使用 annotations
和 parameters
静态属性进行注释.
Angular 2 injectables (classes and constructor functions) are supposed to be annotated with annotations
and parameters
static properties under the hood.
annotations
是一个包含 new
用于可注入类的装饰器的数组:
annotations
is an array that contains new
ed decorators for injectable class:
function SomeComponent(...) {}
SomeComponent.annotations = [new Componenent(...)];
parameters
是一个数组,其中包含构造函数参数的装饰器,每个元素都是一个数组,其中包含用于各个构造函数属性的 new
装饰器列表(类似于 $inject
Angular 1.x 中的属性显式注解):
parameters
is an array that contains decorators for constructor parameters, each element is an array that contains a list of new
ed decorators for respective constructor property (similarly to $inject
property explicit annotation in Angular 1.x):
function Service(someService, anotherService) {}
Service.parameters = [
[new Inject(SomeService)],
[new Inject(AnotherService), new Optional, new SkipSelf]
];
所有类装饰器都是从 扩展而来的TypeDecorator
,意味着它们可以作为函数调用.在这种情况下,使用所谓的 DSL 语法,允许将装饰器与 Class
辅助函数:
All class decorators are extended from TypeDecorator
, meaning that they can be called as functions. In this case so-called DSL syntax is used that allows to chain a decorator with Class
helper function:
var SomeComponent = Componenent(...).Class(...);
Class
也可以单独使用,它从给定的 定义对象并允许使用数组注释constructor
方法(类似于Angular 1.x中的内联数组显式注释):
Class
is also available separately, it constructs a new class from given definition object and allows to annotate constructor
method with array (similarly to inline array explicit annotation in Angular 1.x):
var SomeService = Class({
constructor: [[new Inject(SomeService)], function (someService) {}]
});
Class
帮助程序在最新的框架版本中已弃用.它应该被 ES5 中的原始函数或第三方类助手替换.装饰器支持与类函数直接链接,Componenent(...)(ComponentClass)
.
Class
helper was deprecated in latest framework versions. It is supposed to be replaced with raw functions or third-party class helpers in ES5. Decorators support direct chaining with class functions, Componenent(...)(ComponentClass)
.
一个示例:
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);
这篇关于ES5 和 ES6 中的 Angular 2 依赖注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!