简体   繁体   English

ES5和ES6中的Angular 2依赖注入

[英]Angular 2 dependency injection in ES5 and ES6

Here is a basic TypeScript/ES.next example that uses decorators for DI and follows the syntax suggested by the framework manual: 这是一个基本的TypeScript / ES.next示例,它使用DI的装饰器,并遵循框架手册建议的语法:

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);

How would it be written in in ES5? 如何在ES5中编写?

How would the same thing be done in untranspiled ES6/ES2015? 如何将同样的事情在untranspiled ES6 / ES2015做什么?

How are Injectable and Inject decorators translated in these cases? 在这些情况下,如何翻译可InjectableInject装饰器?

The question particularly applies to real-world ES6 browser implementations that have classes but may use require or System.import instead of ES6 imports. 这个问题特别适用于具有类但可能使用requireSystem.import而不是ES6导入的实际ES6浏览器实现。

To use Angular 2 with ES5 you need this script: 要将Angular 2与ES5一起使用,您需要以下脚本:

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/2.0.0-beta.3/angular2-all.umd.js"></script>

This provides an global variable that contains all of Angular 2. Now you can write ng.core.Component instead of the @Component annotation. 这提供了一个包含所有Angular 2的全局变量。现在您可以编写ng.core.Component而不是@Component注释。 The first parameters of the Constructor are the injectables. 构造函数的第一个参数是注入式。

var Component = ng.core
  Component({
    selector: 'hello-cmp',
    template: 'Hello World!',
    viewProviders: [Service]
  .Class({
    constructor: [Service, function (service) { 
      ...
    }],
  });

And tell the injector that our service parameter is a instance of Service 告诉注入器我们的服务参数是Service一个实例

Component.parameters = [[new ng.core.Inject(Service)]];


The following Exapmle shows the usage of angular2 with ES6 : 以下Exapmle显示了使用ES6的angular2:

import {Component} from 'angular2/core';
import {Service} from './example.service';

let componentAnnotation = new Component({
  selector: 'world-time',
  inputs: ['timeZones'],
  providers: [Service],
  template: `
    ...
  `
});
export class ComponentExample {
   constructor(service) {
    this._service = service;

   }
...

}

WorldTimeComponent.annotations = [componentAnnotation];
WorldTimeComponent.parameters = [[Service]];

In this plunkr you can find a working ES6 example. 在这个plunkr中你可以找到一个有效的ES6例子。

But you can use decorators by using Babel . 但是你可以使用Babel来使用装饰器。 Enabling the optional[]=es7.decorators (in webpack) or by setting your configuration to stage:1 . 启用optional[]=es7.decorators (在webpack中)或将配置设置为stage:1

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. Injectable装饰器特定于Angular 2的TypeScript风格。它允许通过TypeScript类型注释对DI隐式注释类构造函数。 It is redundant in TS and unneeded in JS for injected dependencies that are annotated with Inject . 它在TS中是冗余的,在JS中不需要注入使用Inject注释的依赖项。

Angular 2 injectables (classes and constructor functions) are supposed to be annotated with annotations and parameters static properties under the hood. Angular 2 injectables(类和构造函数)应该在引擎盖下annotationsparameters静态属性。

annotations is an array that contains new ed decorators for injectable class: annotations是一个包含可注入类的new ed装饰器的数组:

function SomeComponent(...) {}
SomeComponent.annotations = [new Componenent(...)];

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): parameters是一个包含构造函数参数的装饰器的数组,每个元素都是一个数组,其中包含各个构造函数属性的new ed装饰器列表(类似于Angular 1.x中的$inject属性显式注释):

function Service(someService, anotherService) {}
Service.parameters = [
  [new Inject(SomeService)],
  [new Inject(AnotherService), new Optional, new SkipSelf]
];

All class decorators are extended from TypeDecorator , meaning that they can be called as functions. 所有类装饰器都从TypeDecorator扩展,这意味着它们可以作为函数调用。 In this case so-called DSL syntax is used that allows to chain a decorator with Class helper function : 在这种情况下,使用所谓的DSL语法,允许使用Class辅助函数链接装饰器:

var SomeComponent = Componenent(...).Class(...);

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): Class也可单独使用,它从给定的定义对象构造一个新类,并允许使用数组注释constructor方法(类似于Angular 1.x中的内联数组显式注释):

var SomeService = Class({
  constructor: [[new Inject(SomeService)], function (someService) {}]
});

Class helper was deprecated in latest framework versions. 在最新的框架版本中不推荐使用Class助手。 It is supposed to be replaced with raw functions or third-party class helpers in ES5. 它应该被ES5中的原始函数或第三方类助手替换。 Decorators support direct chaining with class functions, Componenent(...)(ComponentClass) . 装饰器支持直接链接类函数, Componenent(...)(ComponentClass)

Angular 2/4 ES6 with System.import 带有System.import Angular 2/4 ES6

An example : 一个例子

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 with UMD modules and ng global 具有UMD模块和ng全局的Angular 2/4 ES5

An example : 一个例子

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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM