review for dependency-injection.jade in guide.
This commit is contained in:
parent
3ba0e541e1
commit
990ecd8f70
@ -82,8 +82,8 @@ include ../_util-fns
|
|||||||
to share services that have been created previously for other consumers.
|
to share services that have been created previously for other consumers.
|
||||||
|
|
||||||
现在,每辆车都有它自己的引擎。它不能和其它车辆共享引擎。
|
现在,每辆车都有它自己的引擎。它不能和其它车辆共享引擎。
|
||||||
虽然这对于汽车来说还算可以理解,但是我们设想一下那些应该被共享的依赖,比如到厂家服务中心的车载无线(译注:汽车的一种设备,用于联系厂家)。
|
虽然这对于汽车来说还算可以理解,但是我们设想一下那些应该被共享的依赖,比如用来联系厂家服务中心的车载无线。
|
||||||
我们的车缺乏必要的弹性,来共享当初给其他消费者创建的车载无线。
|
我们的车缺乏必要的弹性,无法共享当初给其他消费者创建的车载无线。
|
||||||
|
|
||||||
When we write tests for our `Car` we're at the mercy of its hidden dependencies.
|
When we write tests for our `Car` we're at the mercy of its hidden dependencies.
|
||||||
Is it even possible to create a new `Engine` in a test environment?
|
Is it even possible to create a new `Engine` in a test environment?
|
||||||
@ -91,7 +91,7 @@ include ../_util-fns
|
|||||||
Will a new instance of `Engine` make an asynchronous call to the server?
|
Will a new instance of `Engine` make an asynchronous call to the server?
|
||||||
We certainly don't want that going on during our tests.
|
We certainly don't want that going on during our tests.
|
||||||
|
|
||||||
当我们给`Car`类写测试的时候,我们得自己摆弄它那些隐藏的依赖。
|
当我们给`Car`类写测试的时候,我们被它那些隐藏的依赖所摆布。
|
||||||
你以为能在测试环境中成功创建一个新的`Engine`吗?
|
你以为能在测试环境中成功创建一个新的`Engine`吗?
|
||||||
`Engine`自己又依赖什么?那些依赖本身又依赖什么?
|
`Engine`自己又依赖什么?那些依赖本身又依赖什么?
|
||||||
`Engine`的新实例会发起一个到服务器的异步调用吗?
|
`Engine`的新实例会发起一个到服务器的异步调用吗?
|
||||||
@ -139,12 +139,13 @@ include ../_util-fns
|
|||||||
:marked
|
:marked
|
||||||
We also leverage TypeScript's constructor syntax for declaring parameters and properties simultaneously.
|
We also leverage TypeScript's constructor syntax for declaring parameters and properties simultaneously.
|
||||||
|
|
||||||
我们又一次借助TypeScript的构造器语法来同时定义参数和属性。
|
我们同时借助TypeScript的构造器语法来同时定义参数和属性。
|
||||||
// #docregion why-3-2
|
// #docregion why-3-2
|
||||||
:marked
|
:marked
|
||||||
Now we create a car by passing the engine and tires to the constructor.
|
Now we create a car by passing the engine and tires to the constructor.
|
||||||
|
|
||||||
现在,我们通过往构造函数中传入引擎和轮胎来创建一辆车。
|
现在,我们通过往构造函数中传入引擎和轮胎来创建一辆车。
|
||||||
|
|
||||||
// #enddocregion why-3-2
|
// #enddocregion why-3-2
|
||||||
- var stylePattern = { otl: /(new Car.*$)/gm };
|
- var stylePattern = { otl: /(new Car.*$)/gm };
|
||||||
+makeExample('dependency-injection/ts/app/car/car-creations.ts', 'car-ctor-instantiation', '', stylePattern)(format=".")
|
+makeExample('dependency-injection/ts/app/car/car-creations.ts', 'car-ctor-instantiation', '', stylePattern)(format=".")
|
||||||
@ -162,6 +163,7 @@ include ../_util-fns
|
|||||||
If someone extends the `Engine` class, that is not `Car`'s problem.
|
If someone extends the `Engine` class, that is not `Car`'s problem.
|
||||||
|
|
||||||
如果有人扩展了`Engine`类,那就不再是`Car`类的烦恼了。
|
如果有人扩展了`Engine`类,那就不再是`Car`类的烦恼了。
|
||||||
|
|
||||||
// #enddocregion why-4
|
// #enddocregion why-4
|
||||||
// Must copy the following, due to indented +make.
|
// Must copy the following, due to indented +make.
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
@ -244,7 +246,7 @@ include ../_util-fns
|
|||||||
|
|
||||||
When we need a `Car`, we simply ask the injector to get it for us and we're good to go.
|
When we need a `Car`, we simply ask the injector to get it for us and we're good to go.
|
||||||
|
|
||||||
当我们需要一个`Car`时,就简单的请求注入器取得它,然后直接去提车。
|
当我们需要一个`Car`时,就简单的找注入器取车就可以了。
|
||||||
// #enddocregion why-8
|
// #enddocregion why-8
|
||||||
+makeExample('dependency-injection/ts/app/car/car-injector.ts','injector-call')(format=".")
|
+makeExample('dependency-injection/ts/app/car/car-injector.ts','injector-call')(format=".")
|
||||||
// #docregion why-9
|
// #docregion why-9
|
||||||
@ -261,7 +263,7 @@ include ../_util-fns
|
|||||||
|
|
||||||
This is what a **dependency injection framework** is all about.
|
This is what a **dependency injection framework** is all about.
|
||||||
|
|
||||||
这就是“什么是**依赖注入框架**”问题的答案。
|
这就是“**依赖注入框架**”存在的原因。
|
||||||
|
|
||||||
Now that we know what dependency injection is and appreciate its benefits,
|
Now that we know what dependency injection is and appreciate its benefits,
|
||||||
let's see how it is implemented in Angular.
|
let's see how it is implemented in Angular.
|
||||||
@ -283,13 +285,14 @@ include ../_util-fns
|
|||||||
That sounds nice. What does it do for us when building components in Angular?
|
That sounds nice. What does it do for us when building components in Angular?
|
||||||
Let's see, one step at a time.
|
Let's see, one step at a time.
|
||||||
|
|
||||||
看起来很美。当我们在Angular中构建组件的时候,它能为我们做什么?
|
听起来很好。当我们在Angular中构建组件的时候,它到底能为我们做什么?
|
||||||
让我们看看,一次一步儿。
|
让我们看看,一次一步儿。
|
||||||
|
|
||||||
We'll begin with a simplified version of the `HeroesComponent`
|
We'll begin with a simplified version of the `HeroesComponent`
|
||||||
that we built in the [The Tour of Heroes](../tutorial/).
|
that we built in the [The Tour of Heroes](../tutorial/).
|
||||||
|
|
||||||
我们从当初在[英雄指南](../tutorial/)中构建过的`HeroesComponent`的一个简化版本开始。
|
我们从当初在[英雄指南](../tutorial/)中构建过的`HeroesComponent`的一个简化版本开始。
|
||||||
|
|
||||||
// #enddocregion di-1
|
// #enddocregion di-1
|
||||||
+makeTabs(
|
+makeTabs(
|
||||||
`dependency-injection/ts/app/heroes/heroes.component.1.ts,
|
`dependency-injection/ts/app/heroes/heroes.component.1.ts,
|
||||||
@ -308,8 +311,8 @@ include ../_util-fns
|
|||||||
Our stripped down version has only one child, `HeroListComponent`,
|
Our stripped down version has only one child, `HeroListComponent`,
|
||||||
which displays a list of heroes.
|
which displays a list of heroes.
|
||||||
|
|
||||||
`HeroesComponent`是*英雄*特性分区中的根组件。它管理着本分区的所有子组件。
|
`HeroesComponent`是*英雄*特性区域的根组件。它管理本分区的所有子组件。
|
||||||
我们简化后的版本只有一个子组件`HeroListComponent`,它显示一个英雄列表。
|
我们简化后的版本只有一个子组件`HeroListComponent`,用来显示一个英雄列表。
|
||||||
// #enddocregion di-2
|
// #enddocregion di-2
|
||||||
// #docregion di-3
|
// #docregion di-3
|
||||||
:marked
|
:marked
|
||||||
@ -335,6 +338,7 @@ include ../_util-fns
|
|||||||
Write this service in its own file. See [this note](#forward-ref) to understand why.
|
Write this service in its own file. See [this note](#forward-ref) to understand why.
|
||||||
|
|
||||||
把这个服务写在一个独立的文件中。参见[这里的说明](#forward-ref)来理解为什么要这样。
|
把这个服务写在一个独立的文件中。参见[这里的说明](#forward-ref)来理解为什么要这样。
|
||||||
|
|
||||||
+makeExample('dependency-injection/ts/app/heroes/hero.service.1.ts',null, 'app/heroes/hero.service.ts' )
|
+makeExample('dependency-injection/ts/app/heroes/hero.service.1.ts',null, 'app/heroes/hero.service.ts' )
|
||||||
// #docregion di-4
|
// #docregion di-4
|
||||||
:marked
|
:marked
|
||||||
@ -342,6 +346,7 @@ include ../_util-fns
|
|||||||
the same mock data as before, but none of its consumers need to know that.
|
the same mock data as before, but none of its consumers need to know that.
|
||||||
|
|
||||||
我们的`HeroService`暴露了`getHeroes`方法,用于返回跟以前一样的模拟数据,但它的消费者不需要知道这一点。
|
我们的`HeroService`暴露了`getHeroes`方法,用于返回跟以前一样的模拟数据,但它的消费者不需要知道这一点。
|
||||||
|
|
||||||
// #enddocregion di-4
|
// #enddocregion di-4
|
||||||
// #docregion di-5
|
// #docregion di-5
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
@ -353,7 +358,7 @@ include ../_util-fns
|
|||||||
We'd also have to rewrite the way components consume our service.
|
We'd also have to rewrite the way components consume our service.
|
||||||
This is important in general, but not to our current story.
|
This is important in general, but not to our current story.
|
||||||
|
|
||||||
我们甚至不能说这是一个真实的服务。
|
我们甚至没有假装这是一个真实的服务。
|
||||||
如果我们真的从一个远端服务器获取数据,这个API必须是异步的,可能得返回
|
如果我们真的从一个远端服务器获取数据,这个API必须是异步的,可能得返回
|
||||||
[ES2015 承诺(Promise)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)。
|
[ES2015 承诺(Promise)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)。
|
||||||
// #enddocregion di-5
|
// #enddocregion di-5
|
||||||
@ -372,10 +377,12 @@ include ../_util-fns
|
|||||||
|
|
||||||
We don't have to create an Angular injector.
|
We don't have to create an Angular injector.
|
||||||
Angular creates an application-wide injector for us during the bootstrap process.
|
Angular creates an application-wide injector for us during the bootstrap process.
|
||||||
|
|
||||||
<a id="bootstrap"></a>
|
<a id="bootstrap"></a>
|
||||||
|
|
||||||
我们并不需要自己创建一个Angular注入器。
|
我们并不需要自己创建一个Angular注入器。
|
||||||
Angular在启动期间会自动为我们创建一个全应用级注入器。
|
Angular在启动期间会自动为我们创建一个全应用级注入器。
|
||||||
|
<a id="bootstrap"></a>
|
||||||
|
|
||||||
// #enddocregion di-configure-injector-1
|
// #enddocregion di-configure-injector-1
|
||||||
+makeExample('dependency-injection/ts/app/main.ts', 'bootstrap', 'app/main.ts (节选)')(format='.')
|
+makeExample('dependency-injection/ts/app/main.ts', 'bootstrap', 'app/main.ts (节选)')(format='.')
|
||||||
// #docregion di-configure-injector-2
|
// #docregion di-configure-injector-2
|
||||||
@ -418,6 +425,7 @@ include ../_util-fns
|
|||||||
:marked
|
:marked
|
||||||
### Registering providers in a component
|
### Registering providers in a component
|
||||||
### 在组件中注册供应商
|
### 在组件中注册供应商
|
||||||
|
|
||||||
Here's a revised `HeroesComponent` that registers the `HeroService`.
|
Here's a revised `HeroesComponent` that registers the `HeroService`.
|
||||||
|
|
||||||
这里是注册了`HeroService`的修改版`HeroesComponent`。
|
这里是注册了`HeroService`的修改版`HeroesComponent`。
|
||||||
@ -428,6 +436,7 @@ include ../_util-fns
|
|||||||
Look closely at the `providers` part of the `@Component` metadata:
|
Look closely at the `providers` part of the `@Component` metadata:
|
||||||
|
|
||||||
仔细看`@Component`元数据中的`providers`部分:
|
仔细看`@Component`元数据中的`providers`部分:
|
||||||
|
|
||||||
// #enddocregion di-register-providers-2
|
// #enddocregion di-register-providers-2
|
||||||
+makeExample('dependency-injection/ts/app/heroes/heroes.component.1.ts','providers')(format='.')
|
+makeExample('dependency-injection/ts/app/heroes/heroes.component.1.ts','providers')(format='.')
|
||||||
// #docregion di-register-providers-3
|
// #docregion di-register-providers-3
|
||||||
@ -441,6 +450,7 @@ include ../_util-fns
|
|||||||
But its child `HeroListComponent` does, so we head there next.
|
But its child `HeroListComponent` does, so we head there next.
|
||||||
|
|
||||||
`HeroesComponent`本身不需要`HeroService`,但它的子组件`HeroListComponent`需要,所以我们再往下看。
|
`HeroesComponent`本身不需要`HeroService`,但它的子组件`HeroListComponent`需要,所以我们再往下看。
|
||||||
|
|
||||||
// #enddocregion di-register-providers-3
|
// #enddocregion di-register-providers-3
|
||||||
// #docregion di-prepare-for-injection-1
|
// #docregion di-prepare-for-injection-1
|
||||||
:marked
|
:marked
|
||||||
@ -480,7 +490,7 @@ include ../_util-fns
|
|||||||
We're writing in TypeScript and have followed the parameter name with a type annotation, `:HeroService`.
|
We're writing in TypeScript and have followed the parameter name with a type annotation, `:HeroService`.
|
||||||
The class is also decorated with the `@Component` decorator (scroll up to confirm that fact).
|
The class is also decorated with the `@Component` decorator (scroll up to confirm that fact).
|
||||||
|
|
||||||
我们正在写TypeScript,并且在参数名后面带有一个类型注解:`:HeroService`。
|
我们利用TypeScript编程,在参数名后面带有一个类型注解:`:HeroService`。
|
||||||
这个类还有一个`@Component`的装饰器(往上翻翻就知道了)。
|
这个类还有一个`@Component`的装饰器(往上翻翻就知道了)。
|
||||||
|
|
||||||
When the TypeScript compiler evaluates this class, it sees the `@Component` decorator and adds class metadata
|
When the TypeScript compiler evaluates this class, it sees the `@Component` decorator and adds class metadata
|
||||||
@ -493,12 +503,13 @@ include ../_util-fns
|
|||||||
That's how the Angular injector knows to inject an instance of the `HeroService` when it
|
That's how the Angular injector knows to inject an instance of the `HeroService` when it
|
||||||
creates a new `HeroListComponent`.
|
creates a new `HeroListComponent`.
|
||||||
|
|
||||||
为什么Angular的注入器会知道当创建`HeroListComponent`时需要注入一个`HeroService`的实例?这就是原理。
|
Angular的注入器是怎么知道在创建`HeroListComponent`时注入一个`HeroService`的实例的?这就是原理。
|
||||||
// #docregion di-create-injector-implicitly-1
|
// #docregion di-create-injector-implicitly-1
|
||||||
:marked
|
:marked
|
||||||
<a id="di-metadata"></a>
|
<a id="di-metadata"></a>
|
||||||
### Creating the injector (implicitly)
|
### Creating the injector (implicitly)
|
||||||
### 创建注入器(隐式的)
|
### 创建注入器(隐式的)
|
||||||
|
|
||||||
When we introduced the idea of an injector above, we showed how to create
|
When we introduced the idea of an injector above, we showed how to create
|
||||||
an injector and use it to create a new `Car`.
|
an injector and use it to create a new `Car`.
|
||||||
|
|
||||||
@ -523,6 +534,7 @@ include ../_util-fns
|
|||||||
:marked
|
:marked
|
||||||
### Singleton services
|
### Singleton services
|
||||||
### 单例服务
|
### 单例服务
|
||||||
|
|
||||||
Dependencies are singletons within the scope of an injector.
|
Dependencies are singletons within the scope of an injector.
|
||||||
In our example, a single `HeroService` instance is shared among the
|
In our example, a single `HeroService` instance is shared among the
|
||||||
`HeroesComponent` and its `HeroListComponent` children.
|
`HeroesComponent` and its `HeroListComponent` children.
|
||||||
@ -543,16 +555,18 @@ include ../_util-fns
|
|||||||
:marked
|
:marked
|
||||||
### Testing the component
|
### Testing the component
|
||||||
### 测试组件
|
### 测试组件
|
||||||
|
|
||||||
We emphasized earlier that designing a class for dependency injection makes the class easier to test.
|
We emphasized earlier that designing a class for dependency injection makes the class easier to test.
|
||||||
Listing dependencies as constructor parameters may be all we need to test application parts effectively.
|
Listing dependencies as constructor parameters may be all we need to test application parts effectively.
|
||||||
|
|
||||||
我们前面强调过,设计一个适合依赖注入的类,可以让这个类更容易测试。
|
我们前面强调过,设计一个适合依赖注入的类,可以让这个类更容易测试。
|
||||||
在构造函数的参数中列出依赖,就是当我们要对应用的一部分进行有效测试时所要做的一切了。
|
要有效的测试应用的一部分,所有我们所需要做的,就只是在构造函数的参数中列出依赖。
|
||||||
|
|
||||||
For example, we can create a new `HeroListComponent` with a mock service that we can manipulate
|
For example, we can create a new `HeroListComponent` with a mock service that we can manipulate
|
||||||
under test:
|
under test:
|
||||||
|
|
||||||
比如,我们可以使用一个mock服务来创建新的`HeroListComponent`实例,以便我们可以在测试中操纵它:
|
比如,我们可以使用一个mock服务来创建新的`HeroListComponent`实例,以便我们可以在测试中操纵它:
|
||||||
|
|
||||||
// #enddocregion di-testing-component-1
|
// #enddocregion di-testing-component-1
|
||||||
+makeExample('dependency-injection/ts/app/test.component.ts', 'spec')(format='.')
|
+makeExample('dependency-injection/ts/app/test.component.ts', 'spec')(format='.')
|
||||||
// #docregion di-testing-component-2
|
// #docregion di-testing-component-2
|
||||||
@ -565,7 +579,8 @@ include ../_util-fns
|
|||||||
// #docregion di-service-service-1
|
// #docregion di-service-service-1
|
||||||
:marked
|
:marked
|
||||||
### When the service needs a service
|
### When the service needs a service
|
||||||
### 如果此服务需要别的服务
|
### 服务需要别的服务
|
||||||
|
|
||||||
Our `HeroService` is very simple. It doesn't have any dependencies of its own.
|
Our `HeroService` is very simple. It doesn't have any dependencies of its own.
|
||||||
|
|
||||||
我们的`HeroService`非常简单。它本身不需要任何依赖。
|
我们的`HeroService`非常简单。它本身不需要任何依赖。
|
||||||
@ -579,7 +594,7 @@ include ../_util-fns
|
|||||||
|
|
||||||
Here is the revision compared to the original.
|
Here is the revision compared to the original.
|
||||||
|
|
||||||
下面是相对于原始类的修改:
|
下面是在原来的类的基础上做的修改:
|
||||||
// #enddocregion di-service-service-1
|
// #enddocregion di-service-service-1
|
||||||
+makeTabs(
|
+makeTabs(
|
||||||
`dependency-injection/ts/app/heroes/hero.service.2.ts,
|
`dependency-injection/ts/app/heroes/hero.service.2.ts,
|
||||||
@ -594,6 +609,7 @@ include ../_util-fns
|
|||||||
|
|
||||||
现在,这个构造函数会要求一个`Logger`类的实例注入进来,并且把它存到一个名为`_logger`的私有属性中。
|
现在,这个构造函数会要求一个`Logger`类的实例注入进来,并且把它存到一个名为`_logger`的私有属性中。
|
||||||
当别人要求获得英雄数据时,我们会在`getHeroes`方法中使用这个属性。
|
当别人要求获得英雄数据时,我们会在`getHeroes`方法中使用这个属性。
|
||||||
|
|
||||||
// #enddocregion di-service-service-2
|
// #enddocregion di-service-service-2
|
||||||
// #docregion di-injectable-1
|
// #docregion di-injectable-1
|
||||||
- var lang = current.path[1]
|
- var lang = current.path[1]
|
||||||
@ -605,13 +621,14 @@ include ../_util-fns
|
|||||||
<a id="injectable"></a>
|
<a id="injectable"></a>
|
||||||
### Why @Injectable?
|
### Why @Injectable?
|
||||||
### 为什么要加@Injectable?
|
### 为什么要加@Injectable?
|
||||||
|
|
||||||
Notice the `@Injectable()` #{decoration} above the service class.
|
Notice the `@Injectable()` #{decoration} above the service class.
|
||||||
We haven't seen `@Injectable()` before.
|
We haven't seen `@Injectable()` before.
|
||||||
As it happens, we could have added it to our first version of `HeroService`.
|
As it happens, we could have added it to our first version of `HeroService`.
|
||||||
We didn't bother because we didn't need it then.
|
We didn't bother because we didn't need it then.
|
||||||
|
|
||||||
注意上面这个服务类的 `@Injectable()` #{decorationCn}。但我们以前从没见过`@Injectable()`。
|
注意上面这个服务类的 `@Injectable()` #{decorationCn}。但我们以前从没见过`@Injectable()`。
|
||||||
当初,我们本可以把它加到第一版的`HeroService`上。
|
其实我们可以把它加到第一版的`HeroService`上。
|
||||||
但我们没有那么做,因为那时候还不需要它。
|
但我们没有那么做,因为那时候还不需要它。
|
||||||
|
|
||||||
We need it now... now that our service has an injected dependency.
|
We need it now... now that our service has an injected dependency.
|
||||||
@ -631,12 +648,14 @@ include ../_util-fns
|
|||||||
- var any_decoratorCn = lang == 'dart' ? '' : 'TypeScript会为任何带有装饰器的类生成元数据,而且会为任何装饰器都生成。'
|
- var any_decoratorCn = lang == 'dart' ? '' : 'TypeScript会为任何带有装饰器的类生成元数据,而且会为任何装饰器都生成。'
|
||||||
.callout.is-helpful
|
.callout.is-helpful
|
||||||
header Suggestion: add @Injectable() to every service class
|
header Suggestion: add @Injectable() to every service class
|
||||||
|
|
||||||
header 建议:为每一个服务类添加@Injectable()
|
header 建议:为每一个服务类添加@Injectable()
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
We recommend adding `@Injectable()` to every service class, even those that don't have dependencies
|
We recommend adding `@Injectable()` to every service class, even those that don't have dependencies
|
||||||
and, therefore, do not technically require it. Here's why:
|
and, therefore, do not technically require it. Here's why:
|
||||||
|
|
||||||
我们建议为每个服务类都添加`@Injectable()`装饰器,即使它们因为目前没有任何依赖,而在技术上并不需要它。这是因为:
|
我们建议为每个服务类都添加`@Injectable()`装饰器,即使它们因为目前没有任何依赖,在技术上并不需要它。这是因为:
|
||||||
ul(style="font-size:inherit")
|
ul(style="font-size:inherit")
|
||||||
li <b>Future proofing:</b> No need to remember <code>@Injectable()</code> when we add a dependency later.
|
li <b>Future proofing:</b> No need to remember <code>@Injectable()</code> when we add a dependency later.
|
||||||
li <b>面向未来:</b> 在我们将来添加依赖时,不用怕忘了添加<code>@Injectable()</code>。
|
li <b>面向未来:</b> 在我们将来添加依赖时,不用怕忘了添加<code>@Injectable()</code>。
|
||||||
@ -664,6 +683,7 @@ include ../_util-fns
|
|||||||
.callout.is-critical
|
.callout.is-critical
|
||||||
header Always include the parentheses
|
header Always include the parentheses
|
||||||
header 总要带着括号
|
header 总要带着括号
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
Always use `@Injectable()`, not just `@Injectable`.
|
Always use `@Injectable()`, not just `@Injectable`.
|
||||||
Our application will fail mysteriously if we forget the parentheses.
|
Our application will fail mysteriously if we forget the parentheses.
|
||||||
@ -676,12 +696,17 @@ include ../_util-fns
|
|||||||
:marked
|
:marked
|
||||||
## Creating and registering a logger service
|
## Creating and registering a logger service
|
||||||
## 创建和注册日志服务
|
## 创建和注册日志服务
|
||||||
|
|
||||||
We're injecting a logger into our `HeroService` in two steps:
|
We're injecting a logger into our `HeroService` in two steps:
|
||||||
|
|
||||||
要把日志服务注入到`HeroService`中需要两步:
|
要把日志服务注入到`HeroService`中需要两步:
|
||||||
|
|
||||||
1. Create the logger service.
|
1. Create the logger service.
|
||||||
|
|
||||||
1. 创建日志服务。
|
1. 创建日志服务。
|
||||||
|
|
||||||
1. Register it with the application.
|
1. Register it with the application.
|
||||||
|
|
||||||
1. 把它注册到应用中。
|
1. 把它注册到应用中。
|
||||||
|
|
||||||
The logger service implementation is no big deal.
|
The logger service implementation is no big deal.
|
||||||
@ -699,12 +724,14 @@ include ../_util-fns
|
|||||||
|
|
||||||
我们很可能在应用的任何地方都使用同一个日志服务的实例。
|
我们很可能在应用的任何地方都使用同一个日志服务的实例。
|
||||||
所以,我们把它放到`app/`目录下,也就是应用的顶级,并把它注册到我们的根组件`AppComponent`上,放到元数据中的`providers`数组里。
|
所以,我们把它放到`app/`目录下,也就是应用的顶级,并把它注册到我们的根组件`AppComponent`上,放到元数据中的`providers`数组里。
|
||||||
|
|
||||||
+makeExample('dependency-injection/ts/app/providers.component.ts','providers-logger', 'app/app.component.ts (节选)')
|
+makeExample('dependency-injection/ts/app/providers.component.ts','providers-logger', 'app/app.component.ts (节选)')
|
||||||
// #docregion logger-service-3
|
// #docregion logger-service-3
|
||||||
:marked
|
:marked
|
||||||
If we forget to register the logger, Angular throws an exception when it first looks for the logger:
|
If we forget to register the logger, Angular throws an exception when it first looks for the logger:
|
||||||
|
|
||||||
如果我们忘了注册这个日志服务,Angular会在首次查找这个日志服务时,抛出一个异常。
|
如果我们忘了注册这个日志服务,Angular会在首次查找这个日志服务时,抛出一个异常。
|
||||||
|
|
||||||
code-example(format, language="html").
|
code-example(format, language="html").
|
||||||
EXCEPTION: No provider for Logger! (HeroListComponent -> HeroService -> Logger)
|
EXCEPTION: No provider for Logger! (HeroListComponent -> HeroService -> Logger)
|
||||||
|
|
||||||
@ -720,8 +747,8 @@ code-example(format, language="html").
|
|||||||
create and inject into a new `HeroListComponent`.
|
create and inject into a new `HeroListComponent`.
|
||||||
|
|
||||||
Angular这是在告诉我们,依赖注入器找不到日志服务的*供应商*。
|
Angular这是在告诉我们,依赖注入器找不到日志服务的*供应商*。
|
||||||
而它需要这个供应商来创建一个`Logger`实例,以便注入到一个`HeroService`的新实例中,
|
它需要这个供应商来创建一个`Logger`实例,以便注入到一个`HeroService`的新实例中,
|
||||||
而`HeroService`会在创建`HeroListComponent`的新实例时被创建和注入进去。
|
而`HeroService`的新实例在创建`HeroListComponent`的新实例时需要被创建和注入。
|
||||||
|
|
||||||
The chain of creations started with the `Logger` provider. The *provider* is the subject of our next section.
|
The chain of creations started with the `Logger` provider. The *provider* is the subject of our next section.
|
||||||
|
|
||||||
@ -730,15 +757,18 @@ code-example(format, language="html").
|
|||||||
But wait! What if the logger is optional?
|
But wait! What if the logger is optional?
|
||||||
|
|
||||||
但是,等一下,如果这个日志服务是可选的呢?
|
但是,等一下,如果这个日志服务是可选的呢?
|
||||||
|
|
||||||
<a id="optional"></a>
|
<a id="optional"></a>
|
||||||
### Optional dependencies
|
### Optional dependencies
|
||||||
|
|
||||||
### 可选的依赖
|
### 可选的依赖
|
||||||
|
|
||||||
Our `HeroService` currently requires a `Logger`. What if we could get by without a logger?
|
Our `HeroService` currently requires a `Logger`. What if we could get by without a logger?
|
||||||
We'd use it if we had it, ignore it if we didn't. We can do that.
|
We'd use it if we had it, ignore it if we didn't. We can do that.
|
||||||
|
|
||||||
我们的`HeroService`目前需要`Logger`。如果我们想单独获取它而不用带着日志服务呢?
|
我们的`HeroService`目前需要`Logger`。如果我们在没有日志服务的时候可以照样继续工作?
|
||||||
我们期望的是:有就用,没有就忽略。这也好办。
|
我们有它就用,没它就忽略。这也好办。
|
||||||
|
|
||||||
// #enddocregion logger-service-4
|
// #enddocregion logger-service-4
|
||||||
|
|
||||||
// TypeScript only?
|
// TypeScript only?
|
||||||
@ -746,6 +776,7 @@ code-example(format, language="html").
|
|||||||
First import the `@Optional()` decorator.
|
First import the `@Optional()` decorator.
|
||||||
|
|
||||||
首先引入`@Optional()`装饰器。
|
首先引入`@Optional()`装饰器。
|
||||||
|
|
||||||
+makeExample('dependency-injection/ts/app/providers.component.ts','import-optional')(format='.')
|
+makeExample('dependency-injection/ts/app/providers.component.ts','import-optional')(format='.')
|
||||||
|
|
||||||
// #docregion logger-service-5
|
// #docregion logger-service-5
|
||||||
@ -804,7 +835,7 @@ code-example(format, language="html").
|
|||||||
The injector relies on **providers** to create instances of the services
|
The injector relies on **providers** to create instances of the services
|
||||||
that the injector injects into components and other services.
|
that the injector injects into components and other services.
|
||||||
|
|
||||||
供应商*供应*所依赖值的一个具体的运行期版本。
|
供应商*提供*所需依赖值的一个具体的运行期版本。
|
||||||
注入器依靠**供应商们**来创建服务的实例,它会被注入器注入到组件或其它服务中。
|
注入器依靠**供应商们**来创建服务的实例,它会被注入器注入到组件或其它服务中。
|
||||||
|
|
||||||
We must register a service *provider* with the injector, or it won't know how to create the service.
|
We must register a service *provider* with the injector, or it won't know how to create the service.
|
||||||
@ -814,6 +845,7 @@ code-example(format, language="html").
|
|||||||
Earlier we registered the `Logger` service in the `providers` array of the metadata for the `AppComponent` like this:
|
Earlier we registered the `Logger` service in the `providers` array of the metadata for the `AppComponent` like this:
|
||||||
|
|
||||||
以前,我们通过`AppComponent`元数据中的`providers`数组注册过`Logger`服务,就像这样:
|
以前,我们通过`AppComponent`元数据中的`providers`数组注册过`Logger`服务,就像这样:
|
||||||
|
|
||||||
// #enddocregion providers-1
|
// #enddocregion providers-1
|
||||||
+makeExample('dependency-injection/ts/app/providers.component.ts','providers-logger')
|
+makeExample('dependency-injection/ts/app/providers.component.ts','providers-logger')
|
||||||
// #docregion providers-2
|
// #docregion providers-2
|
||||||
@ -852,6 +884,7 @@ code-example(format, language="html").
|
|||||||
What matters is that the injector has a provider to go to when it needs a `Logger`.
|
What matters is that the injector has a provider to go to when it needs a `Logger`.
|
||||||
|
|
||||||
问题是:当注入器需要一个`Logger`时,它得先有一个供应商。
|
问题是:当注入器需要一个`Logger`时,它得先有一个供应商。
|
||||||
|
|
||||||
// #enddocregion providers-2
|
// #enddocregion providers-2
|
||||||
// #docregion providers-provide-1
|
// #docregion providers-provide-1
|
||||||
:marked
|
:marked
|
||||||
@ -861,7 +894,9 @@ code-example(format, language="html").
|
|||||||
// Don't mention provide function in Dart
|
// Don't mention provide function in Dart
|
||||||
:marked
|
:marked
|
||||||
### The *Provider* class and *provide* function
|
### The *Provider* class and *provide* function
|
||||||
|
|
||||||
### *Provider*类和*provide*函数
|
### *Provider*类和*provide*函数
|
||||||
|
|
||||||
// #docregion providers-provide-1-1
|
// #docregion providers-provide-1-1
|
||||||
:marked
|
:marked
|
||||||
We wrote the `providers` array like this:
|
We wrote the `providers` array like this:
|
||||||
@ -891,14 +926,14 @@ code-example(format, language="html").
|
|||||||
In both approaches — `Provider` class and `provide` function —
|
In both approaches — `Provider` class and `provide` function —
|
||||||
we supply two arguments.
|
we supply two arguments.
|
||||||
|
|
||||||
在这两种方式 —— `Provider`类和`provide`函数 —— 中,我们提供了两个参数。
|
在这两种方式里——在`Provider`类和`provide`函数中——我们提供了两个参数。
|
||||||
// #enddocregion providers-provide-4-1
|
// #enddocregion providers-provide-4-1
|
||||||
// #docregion providers-provide-4-2
|
// #docregion providers-provide-4-2
|
||||||
:marked
|
:marked
|
||||||
The first is the [token](#token) that serves as the key for both locating a dependency value
|
The first is the [token](#token) that serves as the key for both locating a dependency value
|
||||||
and registering the provider.
|
and registering the provider.
|
||||||
|
|
||||||
第一个是[token](#token),它作为键值(key)使用,用于定位依赖值,以及注册这个供应商。
|
第一个是[令牌token](#token),它作为键值(key)使用,用于定位依赖值,以及注册这个供应商。
|
||||||
// #enddocregion providers-provide-4-2
|
// #enddocregion providers-provide-4-2
|
||||||
|
|
||||||
// Dart is different here (uses an optional parameter)
|
// Dart is different here (uses an optional parameter)
|
||||||
@ -914,26 +949,30 @@ code-example(format, language="html").
|
|||||||
:marked
|
:marked
|
||||||
<a id="class-provider"></a>
|
<a id="class-provider"></a>
|
||||||
### Alternative class providers
|
### Alternative class providers
|
||||||
### 另外的“类”供应商
|
|
||||||
|
### 其他的“类”供应商
|
||||||
|
|
||||||
Occasionally we'll ask a different class to provide the service.
|
Occasionally we'll ask a different class to provide the service.
|
||||||
The following code tells the injector
|
The following code tells the injector
|
||||||
to return a `BetterLogger` when something asks for the `Logger`.
|
to return a `BetterLogger` when something asks for the `Logger`.
|
||||||
|
|
||||||
某些时候,我们会请求另一个类来供应此服务。
|
某些时候,我们会请求一个不同的类来提供服务。
|
||||||
下列代码告诉注入器:当有人请求一个`Logger`时,请返回一个`BetterLogger`。
|
下列代码告诉注入器:当有人请求一个`Logger`时,请返回一个`BetterLogger`。
|
||||||
// #enddocregion providers-alternative-1
|
// #enddocregion providers-alternative-1
|
||||||
+makeExample('dependency-injection/ts/app/providers.component.ts','providers-4')
|
+makeExample('dependency-injection/ts/app/providers.component.ts','providers-4')
|
||||||
// #docregion providers-alternative-2
|
// #docregion providers-alternative-2
|
||||||
:marked
|
:marked
|
||||||
### Class provider with dependencies
|
### Class provider with dependencies
|
||||||
|
|
||||||
### 带依赖的类供应商
|
### 带依赖的类供应商
|
||||||
|
|
||||||
Maybe an `EvenBetterLogger` could display the user name in the log message.
|
Maybe an `EvenBetterLogger` could display the user name in the log message.
|
||||||
This logger gets the user from the injected `UserService`,
|
This logger gets the user from the injected `UserService`,
|
||||||
which happens also to be injected at the application level.
|
which happens also to be injected at the application level.
|
||||||
|
|
||||||
也许一个`EvenBetterLogger`(更好的日志)可以在日志消息中显示用户名。
|
也许一个`EvenBetterLogger`(更好的日志)可以在日志消息中显示用户名。
|
||||||
这个日志服务从一个注入进来的`UserService`中取得用户,`UserService`通常也会在应用级被注入。
|
这个日志服务从一个注入进来的`UserService`中取得用户,`UserService`通常也会在应用级被注入。
|
||||||
|
|
||||||
// #enddocregion providers-alternative-2
|
// #enddocregion providers-alternative-2
|
||||||
+makeExample('dependency-injection/ts/app/providers.component.ts','EvenBetterLogger')
|
+makeExample('dependency-injection/ts/app/providers.component.ts','EvenBetterLogger')
|
||||||
// #docregion providers-alternative-3
|
// #docregion providers-alternative-3
|
||||||
@ -946,6 +985,7 @@ code-example(format, language="html").
|
|||||||
// #docregion providers-aliased-1
|
// #docregion providers-aliased-1
|
||||||
:marked
|
:marked
|
||||||
### Aliased class providers
|
### Aliased class providers
|
||||||
|
|
||||||
### 别名类供应商
|
### 别名类供应商
|
||||||
|
|
||||||
Suppose an old component depends upon an `OldLogger` class.
|
Suppose an old component depends upon an `OldLogger` class.
|
||||||
@ -964,7 +1004,7 @@ code-example(format, language="html").
|
|||||||
when a component asks for either the new or the old logger.
|
when a component asks for either the new or the old logger.
|
||||||
The `OldLogger` should be an alias for `NewLogger`.
|
The `OldLogger` should be an alias for `NewLogger`.
|
||||||
|
|
||||||
当组件请求无论是新的还是老的日志服务时,依赖注入器注入的都应该是同一个单例对象。
|
不管组件请求的是新的还是老的日志服务,依赖注入器注入的都应该是同一个单例对象。
|
||||||
也就是说,`OldLogger`应该是`NewLogger`的一个别名。
|
也就是说,`OldLogger`应该是`NewLogger`的一个别名。
|
||||||
|
|
||||||
We certainly do not want two different `NewLogger` instances in our app.
|
We certainly do not want two different `NewLogger` instances in our app.
|
||||||
@ -979,13 +1019,16 @@ code-example(format, language="html").
|
|||||||
The solution: Alias with the `useExisting` option.
|
The solution: Alias with the `useExisting` option.
|
||||||
|
|
||||||
解决方案:使用`useExisting`选项指定别名。
|
解决方案:使用`useExisting`选项指定别名。
|
||||||
|
|
||||||
// #enddocregion providers-aliased-2
|
// #enddocregion providers-aliased-2
|
||||||
+makeExample('dependency-injection/ts/app/providers.component.ts','providers-6b')(format=".")
|
+makeExample('dependency-injection/ts/app/providers.component.ts','providers-6b')(format=".")
|
||||||
// #docregion providers-value-1
|
// #docregion providers-value-1
|
||||||
<a id="value-provider"></a>
|
<a id="value-provider"></a>
|
||||||
:marked
|
:marked
|
||||||
### Value providers
|
### Value providers
|
||||||
|
|
||||||
### 值供应商
|
### 值供应商
|
||||||
|
|
||||||
// #enddocregion providers-value-1
|
// #enddocregion providers-value-1
|
||||||
|
|
||||||
// Typescript only
|
// Typescript only
|
||||||
@ -993,6 +1036,7 @@ code-example(format, language="html").
|
|||||||
Sometimes it's easier to provide a ready-made object rather than ask the injector to create it from a class.
|
Sometimes it's easier to provide a ready-made object rather than ask the injector to create it from a class.
|
||||||
|
|
||||||
有时,提供一个预先做好的对象会比请求注入器从类中创建它更容易。
|
有时,提供一个预先做好的对象会比请求注入器从类中创建它更容易。
|
||||||
|
|
||||||
+makeExample('dependency-injection/ts/app/providers.component.ts','silent-logger')(format=".")
|
+makeExample('dependency-injection/ts/app/providers.component.ts','silent-logger')(format=".")
|
||||||
:marked
|
:marked
|
||||||
Then we register a provider with the `useValue` option,
|
Then we register a provider with the `useValue` option,
|
||||||
@ -1005,6 +1049,7 @@ code-example(format, language="html").
|
|||||||
<a id="factory-provider"></a>
|
<a id="factory-provider"></a>
|
||||||
:marked
|
:marked
|
||||||
### Factory providers
|
### Factory providers
|
||||||
|
|
||||||
### 工厂供应商
|
### 工厂供应商
|
||||||
|
|
||||||
Sometimes we need to create the dependent value dynamically,
|
Sometimes we need to create the dependent value dynamically,
|
||||||
@ -1049,11 +1094,12 @@ code-example(format, language="html").
|
|||||||
:marked
|
:marked
|
||||||
Why? We don't know either. Stuff like this happens.
|
Why? We don't know either. Stuff like this happens.
|
||||||
|
|
||||||
为什么?我们也不知道。事实就是这样。
|
为什么?我们也不知道。这样的事经常发生。
|
||||||
:marked
|
:marked
|
||||||
Instead the `HeroService` constructor takes a boolean flag to control display of secret heroes.
|
Instead the `HeroService` constructor takes a boolean flag to control display of secret heroes.
|
||||||
|
|
||||||
让`HeroService`的构造函数带上一个布尔型的标志,来控制是否显示隐藏的英雄。
|
让`HeroService`的构造函数带上一个布尔型的标志,来控制是否显示隐藏的英雄。
|
||||||
|
|
||||||
// #enddocregion providers-factory-1
|
// #enddocregion providers-factory-1
|
||||||
+makeExample('dependency-injection/ts/app/heroes/hero.service.ts','internals', 'app/heroes/hero.service.ts (节选)')(format='.')
|
+makeExample('dependency-injection/ts/app/heroes/hero.service.ts','internals', 'app/heroes/hero.service.ts (节选)')(format='.')
|
||||||
// #docregion providers-factory-2
|
// #docregion providers-factory-2
|
||||||
@ -1067,6 +1113,7 @@ code-example(format, language="html").
|
|||||||
A factory provider needs a factory function:
|
A factory provider needs a factory function:
|
||||||
|
|
||||||
工厂供应商需要一个工厂方法:
|
工厂供应商需要一个工厂方法:
|
||||||
|
|
||||||
// #enddocregion providers-factory-2
|
// #enddocregion providers-factory-2
|
||||||
+makeExample('dependency-injection/ts/app/heroes/hero.service.provider.ts','factory', 'app/heroes/hero.service.provider.ts (节选)')(format='.')
|
+makeExample('dependency-injection/ts/app/heroes/hero.service.provider.ts','factory', 'app/heroes/hero.service.provider.ts (节选)')(format='.')
|
||||||
// #docregion providers-factory-3
|
// #docregion providers-factory-3
|
||||||
@ -1078,6 +1125,7 @@ code-example(format, language="html").
|
|||||||
We inject both the `Logger` and the `UserService` into the factory provider and let the injector pass them along to the factory function:
|
We inject both the `Logger` and the `UserService` into the factory provider and let the injector pass them along to the factory function:
|
||||||
|
|
||||||
我们同时把`Logger`和`UserService`注入到工厂供应商中,并且让注入器把它们传给工厂方法:
|
我们同时把`Logger`和`UserService`注入到工厂供应商中,并且让注入器把它们传给工厂方法:
|
||||||
|
|
||||||
// #enddocregion providers-factory-3
|
// #enddocregion providers-factory-3
|
||||||
+makeExample('dependency-injection/ts/app/heroes/hero.service.provider.ts','provider', 'app/heroes/hero.service.provider.ts (节选)')(format='.')
|
+makeExample('dependency-injection/ts/app/heroes/hero.service.provider.ts','provider', 'app/heroes/hero.service.provider.ts (节选)')(format='.')
|
||||||
// #docregion providers-factory-4
|
// #docregion providers-factory-4
|
||||||
@ -1092,9 +1140,9 @@ code-example(format, language="html").
|
|||||||
The `Logger` and `UserService` classes serve as tokens for their own class providers.
|
The `Logger` and `UserService` classes serve as tokens for their own class providers.
|
||||||
The injector resolves these tokens and injects the corresponding services into the matching factory function parameters.
|
The injector resolves these tokens and injects the corresponding services into the matching factory function parameters.
|
||||||
|
|
||||||
`deps`属性是一个[供应商Token](#token)的数组。
|
`deps`属性是一个[供应商令牌](#token)数组。
|
||||||
`Logger`和`UserService`类作为它们自身供应商的token。
|
`Logger`和`UserService`类作为它们自身供应商的令牌。
|
||||||
注入器解析这些Token,并且把相应的服务注入到工厂函数参数中所对应的参数中去。
|
注入器解析这些令牌,并且把相应的服务注入到工厂函数参数中所对应的参数中去。
|
||||||
// #enddocregion providers-factory-4
|
// #enddocregion providers-factory-4
|
||||||
// #docregion providers-factory-5
|
// #docregion providers-factory-5
|
||||||
- var lang = current.path[1]
|
- var lang = current.path[1]
|
||||||
@ -1118,6 +1166,7 @@ code-example(format, language="html").
|
|||||||
在这个例子中,我们只在`HeroesComponent`中需要它,
|
在这个例子中,我们只在`HeroesComponent`中需要它,
|
||||||
这里,它代替了元数据`providers`数组中原来的`HeroService`注册。
|
这里,它代替了元数据`providers`数组中原来的`HeroService`注册。
|
||||||
我们来对比一下新的和老的实现:
|
我们来对比一下新的和老的实现:
|
||||||
|
|
||||||
// #enddocregion providers-factory-5
|
// #enddocregion providers-factory-5
|
||||||
+makeTabs(
|
+makeTabs(
|
||||||
`dependency-injection/ts/app/heroes/heroes.component.ts,
|
`dependency-injection/ts/app/heroes/heroes.component.ts,
|
||||||
@ -1131,22 +1180,22 @@ code-example(format, language="html").
|
|||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Dependency injection tokens
|
## Dependency injection tokens
|
||||||
## 依赖注入Token
|
## 依赖注入令牌
|
||||||
|
|
||||||
When we register a provider with an injector, we associate that provider with a dependency injection token.
|
When we register a provider with an injector, we associate that provider with a dependency injection token.
|
||||||
The injector maintains an internal *token-provider* map that it references when
|
The injector maintains an internal *token-provider* map that it references when
|
||||||
asked for a dependency. The token is the key to the map.
|
asked for a dependency. The token is the key to the map.
|
||||||
|
|
||||||
当我们使用注入器注册一个供应商时,实际上是把这个供应商和一个DI Token关联起来了。
|
当我们使用注入器注册一个供应商时,实际上是把这个供应商和一个DI令牌关联起来了。
|
||||||
注入器维护一个内部的*Token-供应商*映射表,这个映射表会在请求一个依赖时被引用到。
|
注入器维护一个内部的*令牌-供应商*映射表,这个映射表会在请求一个依赖时被引用到。
|
||||||
Token就是这个映射表中的键值(key)。
|
令牌就是这个映射表中的键值(key)。
|
||||||
|
|
||||||
In all previous examples, the dependency value has been a class *instance*, and
|
In all previous examples, the dependency value has been a class *instance*, and
|
||||||
the class *type* served as its own lookup key.
|
the class *type* served as its own lookup key.
|
||||||
Here we get a `HeroService` directly from the injector by supplying the `HeroService` type as the token:
|
Here we get a `HeroService` directly from the injector by supplying the `HeroService` type as the token:
|
||||||
|
|
||||||
在以前的所有范例中,依赖值都是一个类*实例*,并且类的*类型*作为它自己的查找键值。
|
在以前的所有范例中,依赖值都是一个类*实例*,并且类的*类型*作为它自己的查找键值。
|
||||||
这种情况下,我们实际上是直接从注入器中以`HeroService`类型作为Token,来获取一个`HeroService` 实例。
|
这种情况下,我们实际上是直接从注入器中以`HeroService`类型作为令牌,来获取一个`HeroService` 实例。
|
||||||
// #enddocregion tokens-1
|
// #enddocregion tokens-1
|
||||||
+makeExample('dependency-injection/ts/app/injector.component.ts','get-hero-service')(format='.')
|
+makeExample('dependency-injection/ts/app/injector.component.ts','get-hero-service')(format='.')
|
||||||
// #docregion tokens-2
|
// #docregion tokens-2
|
||||||
@ -1156,8 +1205,8 @@ code-example(format, language="html").
|
|||||||
and Angular knows to inject the
|
and Angular knows to inject the
|
||||||
service associated with that `HeroService` class token:
|
service associated with that `HeroService` class token:
|
||||||
|
|
||||||
当我们写一个请求注入基于类的依赖的构造函数时,我们是幸运的。
|
写一个需要基于类的依赖注入的构造函数对我们来说是很幸运的。
|
||||||
我们只要以`HeroService`类为类型,定义一个构造函数参数,Angular就会知道把跟`HeroService`类这个Token关联的服务注入进来:
|
我们只要以`HeroService`类为类型,定义一个构造函数参数,Angular就会知道把跟`HeroService`类令牌关联的服务注入进来:
|
||||||
// #enddocregion tokens-2
|
// #enddocregion tokens-2
|
||||||
+makeExample('dependency-injection/ts/app/providers.component.ts','provider-8-ctor')(format=".")
|
+makeExample('dependency-injection/ts/app/providers.component.ts','provider-8-ctor')(format=".")
|
||||||
// #docregion tokens-3
|
// #docregion tokens-3
|
||||||
@ -1165,6 +1214,7 @@ code-example(format, language="html").
|
|||||||
This is especially convenient when we consider that most dependency values are provided by classes.
|
This is especially convenient when we consider that most dependency values are provided by classes.
|
||||||
|
|
||||||
这是一个特殊的规约,因为我们考虑到大多数依赖值都是以类的形式提供的。
|
这是一个特殊的规约,因为我们考虑到大多数依赖值都是以类的形式提供的。
|
||||||
|
|
||||||
// #enddocregion tokens-3
|
// #enddocregion tokens-3
|
||||||
|
|
||||||
// #docregion tokens-non-class-deps-1
|
// #docregion tokens-non-class-deps-1
|
||||||
@ -1201,8 +1251,8 @@ code-example(format, language="html").
|
|||||||
|
|
||||||
我们想让这个`config`对象在注入时可用。
|
我们想让这个`config`对象在注入时可用。
|
||||||
我们已经知道可以使用一个[值供应商](#value-provider)来注册一个对象。
|
我们已经知道可以使用一个[值供应商](#value-provider)来注册一个对象。
|
||||||
但是这种情况下我们要把什么用作Token呢?
|
但是这种情况下我们要把什么用作令牌呢?
|
||||||
我们没办法找一个类来当做Token,因为没有`Config`类。
|
我们没办法找一个类来当做令牌,因为没有`Config`类。
|
||||||
|
|
||||||
// Typescript only
|
// Typescript only
|
||||||
<a id="interface"></a>
|
<a id="interface"></a>
|
||||||
@ -1214,7 +1264,7 @@ code-example(format, language="html").
|
|||||||
The `CONFIG` constant has an interface, `Config`. Unfortunately, we
|
The `CONFIG` constant has an interface, `Config`. Unfortunately, we
|
||||||
cannot use a TypeScript interface as a token:
|
cannot use a TypeScript interface as a token:
|
||||||
|
|
||||||
`CONFIG`常量有一个接口:`Config`。不幸的是,我们不能把TypeScript接口用作token:
|
`CONFIG`常量有一个接口:`Config`。不幸的是,我们不能把TypeScript接口用作令牌:
|
||||||
+makeExample('dependency-injection/ts/app/providers.component.ts','providers-9a-interface')(format=".")
|
+makeExample('dependency-injection/ts/app/providers.component.ts','providers-9a-interface')(format=".")
|
||||||
+makeExample('dependency-injection/ts/app/providers.component.ts','provider-9a-ctor-interface')(format=".")
|
+makeExample('dependency-injection/ts/app/providers.component.ts','provider-9a-ctor-interface')(format=".")
|
||||||
:marked
|
:marked
|
||||||
@ -1240,7 +1290,8 @@ h3 OpaqueToken
|
|||||||
p.
|
p.
|
||||||
The solution is to define and use an !{opaquetoken}.
|
The solution is to define and use an !{opaquetoken}.
|
||||||
The definition looks like this:
|
The definition looks like this:
|
||||||
p 解决方案是定义和使用用一个!{opaquetoken}(不透明的Token)。定义方式类似于这样:
|
|
||||||
|
p 解决方案是定义和使用用一个!{opaquetoken}(不透明的令牌)。定义方式类似于这样:
|
||||||
// #enddocregion tokens-opaque-1
|
// #enddocregion tokens-opaque-1
|
||||||
+makeExample('dependency-injection/ts/app/app.config.ts','token')(format='.')
|
+makeExample('dependency-injection/ts/app/app.config.ts','token')(format='.')
|
||||||
:marked
|
:marked
|
||||||
@ -1286,12 +1337,13 @@ p 解决方案是定义和使用用一个!{opaquetoken}(不透明的Token)
|
|||||||
:marked
|
:marked
|
||||||
## Summary
|
## Summary
|
||||||
## 总结
|
## 总结
|
||||||
|
|
||||||
We learned the basics of Angular dependency injection in this chapter.
|
We learned the basics of Angular dependency injection in this chapter.
|
||||||
We can register various kinds of providers,
|
We can register various kinds of providers,
|
||||||
and we know how to ask for an injected object (such as a service) by
|
and we know how to ask for an injected object (such as a service) by
|
||||||
adding a parameter to a constructor.
|
adding a parameter to a constructor.
|
||||||
|
|
||||||
在本章中,我们学会了Angular依赖注入的基础。
|
在本章中,我们学习了Angular依赖注入的基础。
|
||||||
我们可以注册很多种类的供应商,还知道了该如何通过添加构造函数的参数来请求一个被注入对象(比如服务)。
|
我们可以注册很多种类的供应商,还知道了该如何通过添加构造函数的参数来请求一个被注入对象(比如服务)。
|
||||||
|
|
||||||
Angular dependency injection is more capable than we've described.
|
Angular dependency injection is more capable than we've described.
|
||||||
@ -1309,11 +1361,12 @@ p 解决方案是定义和使用用一个!{opaquetoken}(不透明的Token)
|
|||||||
:marked
|
:marked
|
||||||
### Appendix: Working with injectors directly
|
### Appendix: Working with injectors directly
|
||||||
### 附录:直接使用注入器工作
|
### 附录:直接使用注入器工作
|
||||||
|
|
||||||
We rarely work directly with an injector.
|
We rarely work directly with an injector.
|
||||||
Here's an `InjectorComponent` that does.
|
Here's an `InjectorComponent` that does.
|
||||||
|
|
||||||
我们很少直接使用注入器工作。
|
我们很少直接使用注入器工作。
|
||||||
这里是一个`InjectorComponent`,它用到了。
|
这里的`InjectorComponent`直接使用了注入器。
|
||||||
// #enddocregion appendix-explicit-injector-1
|
// #enddocregion appendix-explicit-injector-1
|
||||||
+makeExample('dependency-injection/ts/app/injector.component.ts', 'injector', 'app/injector.component.ts')
|
+makeExample('dependency-injection/ts/app/injector.component.ts', 'injector', 'app/injector.component.ts')
|
||||||
// #docregion appendix-explicit-injector-2
|
// #docregion appendix-explicit-injector-2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user