Angular2 依赖注入 - 多层
Angular2 dependency injection - multiple layer
查看此问题的底部,了解我必须更改哪些内容才能使其正常工作。
我正在尝试弄清楚如何注入一个从另一个文件获取注入的对象。按照 angular.io 5 Min Quickstart and Pascal Precht's article about Dependency Injection 的示例,我成功地将我的 Person2 注入到主应用程序 class。
app.ts:
/// <reference path="typings/angular2/angular2.d.ts" />
import {Component, View, bootstrap} from 'angular2/angular2';
import {Person2} from './person2';
@Component({
selector: 'my-app'
})
@View({
template: '<h1>Hello {{name}}</h1>'
})
class MyAppComponent {
name: string;
constructor(person: Person2) {
this.name = person.name;
}
}
bootstrap(MyAppComponent, [Person2]);
person2.ts:
export class Person2 {
name: string;
constructor() {
this.name = 'Mee!';
}
}
这很好用。现在我尝试注入 Person,它得到 Person2。
person.ts:
import {Inject} from 'angular2/angular2';
export class Person {
name: string;
constructor(@Inject('Person2') person2) {
this.name = person2.name;
}
}
一些关于 person.ts 的注释:
- 我不知道从哪里得到 'angular2/di'。似乎 'angular2/angular2' 有注入,因为打字稿编译器没有抱怨。
- Pascal Precht's article about Dependency Injection 说我可以注入
@Inject(Person2) Person2
或 person: Person2
,但其中 none 有效,因为打字稿编译器不知道从哪里获取 Person2。所以我尝试了 @Inject('Person2') person2
并且至少它得到了编译。
- person.ts 仅当我在 person.ts 中导入 Person2 时才可以用
person: Person2
编译。但是我应该能够将 Person2 注入到 Person 而无需在 Person 中导入它。如果我必须导入我正在注入的东西,那么依赖注入的意义何在,对吗?
已修订 app.ts:
/// <reference path="typings/angular2/angular2.d.ts" />
import {Component, View, bootstrap} from 'angular2/angular2';
import {Person} from './person';
import {Person2} from './person2';
@Component({
selector: 'my-app'
})
@View({
template: '<h1>Hello {{name}}</h1>'
})
class MyAppComponent {
name: string;
constructor(person: Person) {
this.name = person.name;
}
}
bootstrap(MyAppComponent, [Person, Person2]);
当我 运行 修改后的应用程序时,我没有得到预期的结果,但浏览器控制台出现错误 Error during instantiation of Person! (MyAppComponent -> Person).
我做错了什么?
编辑
我尝试了@alexpods 的回答,但仍然没有成功。我做了一个Plunker with compiled js files。如果您将 app.js 行 #27 更改为 [person_1.Person]
,您将看到它不再起作用。
编辑 2:终于我成功了
正如@alexpods 所说,我更改了 app.ts 上的 bootstrap 行及其注入方式。
// you need to import Inject and bind
import {Component, View, bootstrap, Inject, bind} from 'angular2/angular2';
//...../.
// you need to inject using @Inject. person: Person will not work.
constructor(@Inject('Person') person) {
//......
// on top of declaring Person and Person2 as dependencies, you need to associate the string `Person` and `Person2` to actual class, so that @Inject can find them.
bootstrap(MyAppComponent, [Person, Person2, bind('Person').toClass(Person), bind('Person2').toClass(Person2)]);
这还不够:不像 angular.io 5 Min Quickstart 所说的那样,我不得不不包括 --emitDecoratorMetadata
。我的 tsc 命令如下所示:
tsc --watch -m commonjs -t es5 app.ts person.ts person2.ts --experimentalDecorators
这里是another plunker that works.
我正在使用 tsc 版本 1.6.0-beta。
将 'Person2'
字符串的绑定添加到应用程序 bootstrap
(或 MyApComponent
到 bindings
属性):
import {Component, View, bootstrap, bind } from 'angular2/angular2';
// a lot of code ...
bootstrap(MyAppComponent, [Person, Person2, bind('Person2').toClass(Person2)]);
查看此问题的底部,了解我必须更改哪些内容才能使其正常工作。
我正在尝试弄清楚如何注入一个从另一个文件获取注入的对象。按照 angular.io 5 Min Quickstart and Pascal Precht's article about Dependency Injection 的示例,我成功地将我的 Person2 注入到主应用程序 class。
app.ts:
/// <reference path="typings/angular2/angular2.d.ts" />
import {Component, View, bootstrap} from 'angular2/angular2';
import {Person2} from './person2';
@Component({
selector: 'my-app'
})
@View({
template: '<h1>Hello {{name}}</h1>'
})
class MyAppComponent {
name: string;
constructor(person: Person2) {
this.name = person.name;
}
}
bootstrap(MyAppComponent, [Person2]);
person2.ts:
export class Person2 {
name: string;
constructor() {
this.name = 'Mee!';
}
}
这很好用。现在我尝试注入 Person,它得到 Person2。
person.ts:
import {Inject} from 'angular2/angular2';
export class Person {
name: string;
constructor(@Inject('Person2') person2) {
this.name = person2.name;
}
}
一些关于 person.ts 的注释:
- 我不知道从哪里得到 'angular2/di'。似乎 'angular2/angular2' 有注入,因为打字稿编译器没有抱怨。
- Pascal Precht's article about Dependency Injection 说我可以注入
@Inject(Person2) Person2
或person: Person2
,但其中 none 有效,因为打字稿编译器不知道从哪里获取 Person2。所以我尝试了@Inject('Person2') person2
并且至少它得到了编译。 - person.ts 仅当我在 person.ts 中导入 Person2 时才可以用
person: Person2
编译。但是我应该能够将 Person2 注入到 Person 而无需在 Person 中导入它。如果我必须导入我正在注入的东西,那么依赖注入的意义何在,对吗?
已修订 app.ts:
/// <reference path="typings/angular2/angular2.d.ts" />
import {Component, View, bootstrap} from 'angular2/angular2';
import {Person} from './person';
import {Person2} from './person2';
@Component({
selector: 'my-app'
})
@View({
template: '<h1>Hello {{name}}</h1>'
})
class MyAppComponent {
name: string;
constructor(person: Person) {
this.name = person.name;
}
}
bootstrap(MyAppComponent, [Person, Person2]);
当我 运行 修改后的应用程序时,我没有得到预期的结果,但浏览器控制台出现错误 Error during instantiation of Person! (MyAppComponent -> Person).
我做错了什么?
编辑
我尝试了@alexpods 的回答,但仍然没有成功。我做了一个Plunker with compiled js files。如果您将 app.js 行 #27 更改为 [person_1.Person]
,您将看到它不再起作用。
编辑 2:终于我成功了
正如@alexpods 所说,我更改了 app.ts 上的 bootstrap 行及其注入方式。
// you need to import Inject and bind
import {Component, View, bootstrap, Inject, bind} from 'angular2/angular2';
//...../.
// you need to inject using @Inject. person: Person will not work.
constructor(@Inject('Person') person) {
//......
// on top of declaring Person and Person2 as dependencies, you need to associate the string `Person` and `Person2` to actual class, so that @Inject can find them.
bootstrap(MyAppComponent, [Person, Person2, bind('Person').toClass(Person), bind('Person2').toClass(Person2)]);
这还不够:不像 angular.io 5 Min Quickstart 所说的那样,我不得不不包括 --emitDecoratorMetadata
。我的 tsc 命令如下所示:
tsc --watch -m commonjs -t es5 app.ts person.ts person2.ts --experimentalDecorators
这里是another plunker that works.
我正在使用 tsc 版本 1.6.0-beta。
将 'Person2'
字符串的绑定添加到应用程序 bootstrap
(或 MyApComponent
到 bindings
属性):
import {Component, View, bootstrap, bind } from 'angular2/angular2';
// a lot of code ...
bootstrap(MyAppComponent, [Person, Person2, bind('Person2').toClass(Person2)]);