review all "我们" keyword, making the translations more natural.
This commit is contained in:
parent
52c118ef8a
commit
77cdd8bde8
@ -122,7 +122,7 @@ table(width="100%")
|
||||
:marked
|
||||
To filter output in our templates in Angular 1, we use the pipe character (|) and one or more filters.
|
||||
|
||||
要在Angular 1中过滤输出,我们使用管道字符(|)以及一个或多个过滤器。
|
||||
要在Angular 1中过滤输出,使用管道字符(|)以及一个或多个过滤器。
|
||||
|
||||
In this example, we filter the `title` property to uppercase.
|
||||
|
||||
@ -140,7 +140,7 @@ table(width="100%")
|
||||
Many (but not all) of the built-in filters from Angular 1 are
|
||||
built-in pipes in Angular 2.
|
||||
|
||||
在Angular 2中,我们使用相似的语法 —— 用管道字符(|)来过滤输出,但是我们现在直接把它叫做**管道**了。
|
||||
在Angular 2中,我们使用相似的语法 —— 用管道字符(|)来过滤输出,但是现在直接把它叫做**管道**了。
|
||||
很多(但不是所有)Angular 1中的内建过滤器也成了Angular 2中的内建管道。
|
||||
|
||||
See the heading [Filters / Pipes](#Pipes) below for more information.
|
||||
@ -218,7 +218,7 @@ table(width="100%")
|
||||
many applications bootstrap declaratively with the `ng-app` directive,
|
||||
giving it the name of the application's module (`movieHunter`).
|
||||
|
||||
虽然我们可以从代码中引导Angular 1应用,
|
||||
虽然可以从代码中引导Angular 1应用,
|
||||
但很多应用都是通过`ng-app`指令进行声明式引导的,只要给它一个应用模块的名字(`movieHunter`)就可以了。
|
||||
|
||||
td
|
||||
@ -262,7 +262,7 @@ table(width="100%")
|
||||
|
||||
We can specify multiple classes as shown in the second example.
|
||||
|
||||
就像第二个例子中展示的,我们可以指定多个CSS类。
|
||||
就像第二个例子中展示的,可以指定多个CSS类。
|
||||
|
||||
td
|
||||
:marked
|
||||
@ -281,7 +281,7 @@ table(width="100%")
|
||||
|
||||
We can specify multiple classes as shown in the second example.
|
||||
|
||||
就像第二个例子中所展示的那样,我们可以同时指定多个类。
|
||||
就像第二个例子中所展示的那样,可以同时指定多个类。
|
||||
|
||||
Angular 2 also has **class binding**, which is a good way to add or remove a single class
|
||||
as shown in the third example.
|
||||
@ -302,7 +302,7 @@ table(width="100%")
|
||||
:marked
|
||||
In Angular 1, the `ng-click` directive allows us to specify custom behavior when an element is clicked.
|
||||
|
||||
在Angular 1中,`ng-click`指令能让我们指定当元素被点击时的自定义行为。
|
||||
在Angular 1中,`ng-click`指令指定当元素被点击时的自定义行为。
|
||||
|
||||
In the first example, when the button is clicked, the `toggleImage()` method in the controller referenced by the `vm` `controller as` alias is executed.
|
||||
|
||||
@ -325,14 +325,14 @@ table(width="100%")
|
||||
Rather, we define one-way binding from the template view to the component using **event binding**.
|
||||
|
||||
Angular 1基于事件的指令在Angular 2中已经不存在了。
|
||||
不过,我们可以使用**事件绑定**来定义从模板视图到组件的单向数据绑定。
|
||||
不过,可以使用**事件绑定**来定义从模板视图到组件的单向数据绑定。
|
||||
|
||||
For event binding, we define the name of the target event within parenthesis and
|
||||
specify a template statement in quotes to the right of the equals. Angular 2 then
|
||||
sets up an event handler for the target event. When the event is raised, the handler
|
||||
executes the template statement.
|
||||
|
||||
要使用事件绑定,我们把目标事件的名字放在圆括号中,并且使用等号右侧引号中的模板语句对它赋值。
|
||||
要使用事件绑定,把目标事件的名字放在圆括号中,并且使用等号右侧引号中的模板语句对它赋值。
|
||||
然后Angular 2为这个目标时间设置事件处理器。当事件被触发时,这个处理器就会执行模板语句。
|
||||
|
||||
In the first example, when the button is clicked, the `toggleImage()` method in the associated component is executed.
|
||||
@ -403,7 +403,7 @@ table(width="100%")
|
||||
In Angular 2, we use property binding; there is no built-in *hide* directive.
|
||||
See [ng-show](#ng-show) for more information.
|
||||
|
||||
在Angular 2中,并没有一个内建的*hide*指令,我们可以改用属性绑定。
|
||||
在Angular 2中,并没有一个内建的*hide*指令,可以改用属性绑定。
|
||||
参见[ng-show](#ng-show)了解更多。
|
||||
|
||||
tr(style=top)
|
||||
@ -441,7 +441,7 @@ table(width="100%")
|
||||
In Angular 2, we use property binding; there is no built-in *href* directive.
|
||||
We place the element's `href` property in square brackets and set it to a quoted template expression.
|
||||
|
||||
在Angular 2中,并没有内建的*href*指令,我们改用属性绑定。
|
||||
在Angular 2中,并没有内建的*href*指令,改用属性绑定。
|
||||
我们把元素的`href`属性放在方括号中,并把它设成一个引号中的模板表达式。
|
||||
|
||||
For more information on property binding see [Template Syntax](../guide/template-syntax.html#property-binding).
|
||||
@ -593,8 +593,8 @@ table(width="100%")
|
||||
In Angular 2, we use property binding; there is no built-in *show* directive.
|
||||
For hiding and showing elements, we bind to the HTML `hidden` property.
|
||||
|
||||
在Angular 2中,并没有内建的*show*指令,我们可以改用属性绑定。
|
||||
要隐藏或显示一个元素,我们绑定到它的`hidden`属性就可以了。
|
||||
在Angular 2中,并没有内建的*show*指令,可以改用属性绑定。
|
||||
要隐藏或显示一个元素,绑定到它的`hidden`属性就可以了。
|
||||
|
||||
To conditionally display an element, place the element's `hidden` property in square brackets and
|
||||
set it to a quoted template expression that evaluates to the *opposite* of *show*.
|
||||
@ -633,8 +633,8 @@ table(width="100%")
|
||||
In Angular 2, we use property binding; there is no built-in *src* directive.
|
||||
We place the `src` property in square brackets and set it to a quoted template expression.
|
||||
|
||||
在Angular 2中,并没有一个内建的*src*指令,我们可以使用属性绑定。
|
||||
我们把`src`属性放到方括号中,并且把它设为一个引号中的绑定表达式。
|
||||
在Angular 2中,并没有一个内建的*src*指令,可以使用属性绑定。
|
||||
把`src`属性放到方括号中,并且把它设为一个引号中的绑定表达式。
|
||||
|
||||
For more information on property binding see [Template Syntax](../guide/template-syntax.html#property-binding).
|
||||
|
||||
@ -733,9 +733,9 @@ table(width="100%")
|
||||
If that method returns `true`, we see "Excellent choice!".
|
||||
If that methods returns `false`, we see "No movie, sorry!".
|
||||
|
||||
在这个例子中,如果`favoriteHero`没有设置,则`ngSwitch`的值是`null`,并且我们会看到
|
||||
在这个例子中,如果`favoriteHero`没有设置,则`ngSwitch`的值是`null`,我们会看到
|
||||
`*ngSwitchDefault`中的段落“Please enter ...”。
|
||||
如果`favoriteHero`被设置了,它就会通过调用一个组件方法来检查他是否电影中的英雄。
|
||||
如果`favoriteHero`被设置了,它就会通过调用一个组件方法来检查电影英雄。
|
||||
如果该方法返回`true`,我们就会看到“Excellent choice!”。
|
||||
如果该方法返回`false`,我们就会看到“No movie, sorry!”。
|
||||
|
||||
@ -763,7 +763,7 @@ a(id="filters-pipes")
|
||||
Many of the built-in filters in Angular 1 have corresponding pipes in Angular 2.
|
||||
For more information on pipes see [Pipes](../guide/pipes.html).
|
||||
|
||||
Angular 2中的**管道**为我们的模板提供了格式化和数据转换功能,类似于Angular 1中的**过滤器**。
|
||||
Angular 2中的**管道**为模板提供了格式化和数据转换功能,类似于Angular 1中的**过滤器**。
|
||||
Angular 1中的很多内建过滤器在Angular 2中都有对应的管道。
|
||||
要了解管道的更多信息,参见[Pipes](../guide/pipes.html)。
|
||||
|
||||
@ -882,7 +882,7 @@ table(width="100%")
|
||||
|
||||
`SlicePipe`做同样的事,但是*两个参数的顺序是相反的*,以便于JavaScript中的`slice`方法保持一致。
|
||||
第一个参数是起始索引号,第二个参数是限制的数量。
|
||||
和Angular 1中一样,如果我们改用组件中的代码实现此操作,性能将会提升。
|
||||
和Angular 1中一样,如果们改用组件中的代码实现此操作,性能将会提升。
|
||||
|
||||
tr(style=top)
|
||||
td
|
||||
@ -1000,7 +1000,7 @@ table(width="100%")
|
||||
In Angular 1, we often defined an immediately invoked function expression (or IIFE) around our controller code.
|
||||
This kept our controller code out of the global namespace.
|
||||
|
||||
在Angular 1中,我们通常会定义一个立即调用的函数表达式(IIFE)来包裹我们的控制器代码。
|
||||
在Angular 1中,我们通常会定义一个立即调用的函数表达式(IIFE)来包裹控制器代码。
|
||||
这样让控制器代码不会污染全局命名空间。
|
||||
|
||||
td
|
||||
@ -1010,7 +1010,7 @@ table(width="100%")
|
||||
We don't need to worry about this in Angular 2 because we use ES 2015 modules
|
||||
and modules handle the namespacing for us.
|
||||
|
||||
在Angular 2中我们不用担心这个问题,因为我们使用ES 2015的模块,模块会替我们处理命名空间问题。
|
||||
在Angular 2中我们不用担心这个问题,因为使用ES 2015的模块,模块会替我们处理命名空间问题。
|
||||
|
||||
For more information on modules see [Architecture Overview](../guide/architecture.html#module).
|
||||
|
||||
@ -1030,7 +1030,7 @@ table(width="100%")
|
||||
controllers, services, and other code. The second argument defines the list
|
||||
of other modules that this module depends upon.
|
||||
|
||||
在Angular 1中,我们定义一个Angular模块,它将对我们的控制器、服务和其他代码进行跟踪。第二个参数定义该模块依赖的其它模块列表。
|
||||
在Angular 1中,我们定义一个Angular模块,它将对控制器、服务和其他代码进行跟踪。第二个参数定义该模块依赖的其它模块列表。
|
||||
|
||||
td
|
||||
:marked
|
||||
@ -1045,7 +1045,7 @@ table(width="100%")
|
||||
|
||||
We `import` what we need from the module files.
|
||||
|
||||
我们`import`任何我们想从模块文件中得到的东西。
|
||||
我们`import`任何想从模块文件中得到的东西。
|
||||
|
||||
For more information on modules see [Architecture Overview](../guide/architecture.html#module).
|
||||
|
||||
@ -1068,7 +1068,7 @@ table(width="100%")
|
||||
In Angular 1, we have code in each controller that looks up an appropriate Angular module
|
||||
and registers the controller with that module.
|
||||
|
||||
在Angular 1中,我们在每个控制器中都有一些代码,用于找到合适的Angular模块并把该控制器注册进去。
|
||||
在Angular 1中,在每个控制器中都有一些代码,用于找到合适的Angular模块并把该控制器注册进去。
|
||||
|
||||
The first argument is the controller name. The second argument defines the string names of
|
||||
all dependencies injected into this controller, and a reference to the controller function.
|
||||
@ -1092,7 +1092,7 @@ table(width="100%")
|
||||
|
||||
This is how we associate a template with code, which is defined in the component class.
|
||||
|
||||
这就是我们把模板关联到代码的方式,它定义在组件类中。
|
||||
这就是把模板关联到代码的方式,它定义在组件类中。
|
||||
|
||||
For more information on components see [Architecture Overview](../guide/architecture.html#component).
|
||||
|
||||
@ -1198,7 +1198,7 @@ a(id="style-sheets")
|
||||
样式表美化我们的应用程序。
|
||||
在Angular 1中,我们为整个应用程序指定样式表。
|
||||
当应用程序成长一段时间之后,应用程序中很多部分的样式会被合并,导致无法预计的后果。
|
||||
在Angular 2中,我们仍然会为整个应用程序定义样式,不过现在我们也可以把样式表封装在特定的组件中。
|
||||
在Angular 2中,我们仍然会为整个应用程序定义样式,不过现在也可以把样式表封装在特定的组件中。
|
||||
|
||||
table(width="100%")
|
||||
col(width="50%")
|
||||
@ -1229,7 +1229,7 @@ table(width="100%")
|
||||
But we can now also encapsulate styles for our components.
|
||||
|
||||
在Angular2中,我们可以继续在`index.html`中使用link标签来为应用程序定义样式。
|
||||
但是我们也能在组件中封装样式。
|
||||
但是也能在组件中封装样式。
|
||||
|
||||
:marked
|
||||
### StyleUrls
|
||||
|
@ -12,7 +12,7 @@ include ../_util-fns
|
||||
For an in-depth look at each fundamental concepts in component communication, we can find detailed description and
|
||||
samples in the [Component Communication]() document.
|
||||
|
||||
要深入了解组件通讯的各个基本概念,我们可以在[组件通讯Component Communication]()文档中可以找到详细的描述和例子。
|
||||
要深入了解组件通讯的各个基本概念,在[组件通讯Component Communication]()文档中可以找到详细的描述和例子。
|
||||
|
||||
<a id="toc"></a>
|
||||
:marked
|
||||
@ -87,7 +87,7 @@ figure.image-display
|
||||
|
||||
E2E test that all children were instantiated and displayed as expected:
|
||||
|
||||
端到端测试,用于确保所有的子组件都像我们所期待的那样被初始化并显示出来。
|
||||
端到端测试,用于确保所有的子组件都像所期待的那样被初始化并显示出来。
|
||||
|
||||
+makeExample('cb-component-communication/e2e-spec.ts', 'parent-to-child')
|
||||
|
||||
@ -254,7 +254,7 @@ parent-to-child-local-var
|
||||
|
||||
A parent component cannot use data binding to read child properties or invoke child methods. We can do both by creating a template reference variable for the child element and then reference that variable *within the parent template* as seen in the following example.
|
||||
|
||||
父组件不能使用数据绑定来读取子组件的属性或调用子组件的方法。但我们可以在父组件模板里,新建一个本地变量来代表子组件,然后利用这个变量来读取子组件的属性和调用子组件的方法,如下例所示。
|
||||
父组件不能使用数据绑定来读取子组件的属性或调用子组件的方法。但可以在父组件模板里,新建一个本地变量来代表子组件,然后利用这个变量来读取子组件的属性和调用子组件的方法,如下例所示。
|
||||
|
||||
<a id="countdown-timer-example"></a>
|
||||
|
||||
@ -276,7 +276,7 @@ parent-to-child-local-var
|
||||
|
||||
We can place a local variable (`#timer`) on the tag (`<countdown-timer>`) representing the child component. That gives us a reference to the child component itself and the ability to access *any of its properties or methods* from within the parent template.
|
||||
|
||||
我们把本地变量(`#timer`)放到(`<countdown-timer>`)标签中,用来代表子组件。这样父组件的模板就得到了子组件的引用,于是可以在父组件的模板中访问子组件的所有属性和方法。
|
||||
把本地变量(`#timer`)放到(`<countdown-timer>`)标签中,用来代表子组件。这样父组件的模板就得到了子组件的引用,于是可以在父组件的模板中访问子组件的所有属性和方法。
|
||||
|
||||
In this example, we wire parent buttons to the child's `start` and `stop` and use interpolation to display the child's `seconds` property.
|
||||
|
||||
@ -317,11 +317,11 @@ a(id="countdown-tests")
|
||||
|
||||
We can't use the *local variable* technique if an instance of the parent component *class* must read or write child component values or must call child component methods.
|
||||
|
||||
如果父组件的*类*需要读取子组件的属性值或调用子组件的方法,我们就不能使用*本地变量*方法了。
|
||||
如果父组件的*类*需要读取子组件的属性值或调用子组件的方法,就不能使用*本地变量*方法。
|
||||
|
||||
When the parent component *class* requires that kind of access, we ***inject*** the child component into the parent as a *ViewChild*.
|
||||
|
||||
当父组件*类*需要这种访问时,我们可以把子组件作为*ViewChild*,***注入***到父组件里面。
|
||||
当父组件*类*需要这种访问时,可以把子组件作为*ViewChild*,***注入***到父组件里面。
|
||||
|
||||
We'll illustrate this technique with the same [Countdown Timer](#countdown-timer-example) example. We won't change its appearance or behavior. The child [CountdownTimerComponent](#countdown-timer-example) is the same as well.
|
||||
|
||||
@ -331,7 +331,7 @@ a(id="countdown-tests")
|
||||
:marked
|
||||
We are switching from the *local variable* to the *ViewChild* technique solely for the purpose of demonstration.
|
||||
|
||||
我们由*本地变量*切换到*ViewChild*技术的唯一目的就是做示范。
|
||||
由*本地变量*切换到*ViewChild*技术的唯一目的就是做示范。
|
||||
|
||||
:marked
|
||||
Here is the parent, `CountdownViewChildParentComponent`:
|
||||
@ -346,12 +346,12 @@ a(id="countdown-tests")
|
||||
|
||||
We import references to the `ViewChild` decorator and the `AfterViewInit` lifecycle hook.
|
||||
|
||||
我们需要通过`ViewChild`装饰器导入这个引用,并挂上`AfterViewInit`生命周期钩子。
|
||||
需要通过`ViewChild`装饰器导入这个引用,并挂上`AfterViewInit`生命周期钩子。
|
||||
|
||||
We inject the child `CountdownTimerComponent` into the private `timerComponent` property
|
||||
via the `@ViewChild` property decoration.
|
||||
|
||||
我们通过`@ViewChild`属性装饰器,将子组件`CountdownTimerComponent`注入到私有属性`timerComponent`里面。
|
||||
通过`@ViewChild`属性装饰器,将子组件`CountdownTimerComponent`注入到私有属性`timerComponent`里面。
|
||||
|
||||
The `#timer` local variable is gone from the component metadata. Instead we bind the buttons to the parent component's own `start` and `stop` methods and present the ticking seconds in an interpolation around the parent component's `seconds` method.
|
||||
|
||||
@ -367,11 +367,11 @@ a(id="countdown-tests")
|
||||
|
||||
Then Angular calls the `ngAfterViewInit` lifecycle hook at which time it is *too late* to update the parent view's display of the countdown seconds. Angular's unidirectional data flow rule prevents us from updating the parent view's in the same cycle. We have to *wait one turn* before we can display the seconds.
|
||||
|
||||
然后Angular会调用`ngAfterViewInit`生命周期钩子,但这时候再更新父组件视图的倒计时就已经太晚了。Angular的单向数据流规则会阻止我们在同一个周期内更新父组件视图。我们在显示秒数之前会被迫*再等一轮儿*。
|
||||
然后Angular会调用`ngAfterViewInit`生命周期钩子,但这时候再更新父组件视图的倒计时就已经太晚了。Angular的单向数据流规则会阻止在同一个周期内更新父组件视图。我们在显示秒数之前会被迫*再等一轮儿*。
|
||||
|
||||
We use `setTimeout` to wait one tick and then revise the `seconds` method so that it takes future values from the timer component.
|
||||
|
||||
我们使用`setTimeout`来等下一轮儿,然后改写`seconds`方法,这样它接下来就会从注入的这个计时器组件里获取秒数的值。
|
||||
使用`setTimeout`来等下一轮儿,然后改写`seconds`方法,这样它接下来就会从注入的这个计时器组件里获取秒数的值。
|
||||
|
||||
### Test it
|
||||
### 测试
|
||||
@ -422,11 +422,11 @@ a(id="countdown-tests")
|
||||
:marked
|
||||
Notice that we capture the `subscription` and unsubscribe when the `AstronautComponent` is destroyed. This is a memory-leak guard step. There is no actual risk in this app because the lifetime of a `AstronautComponent` is the same as the lifetime of the app itself. That *would not* always be true in a more complex application.
|
||||
|
||||
注意,我们通过`subscription`服务订阅任务,并在`AstronautComponent`被销毁的时候退订。这是一个用于防止内存泄漏的保护措施。实际上,在这个应用程序中并没有这个风险,因为`AstronautComponent`的生命期和应用程序的生命期一样长。但在更复杂的应用程序环境中就不一定了。
|
||||
注意,通过`subscription`服务订阅任务,并在`AstronautComponent`被销毁的时候退订。这是一个用于防止内存泄漏的保护措施。实际上,在这个应用程序中并没有这个风险,因为`AstronautComponent`的生命期和应用程序的生命期一样长。但在更复杂的应用程序环境中就不一定了。
|
||||
|
||||
We do not add this guard to the `MissionControlComponent` because, as the parent, it controls the lifetime of the `MissionService`.
|
||||
|
||||
我们不需要在`MissionControlComponent`中添加这个保护措施,因为作为父组件,它控制着`MissionService`的生命期。
|
||||
不需要在`MissionControlComponent`中添加这个保护措施,因为作为父组件,它控制着`MissionService`的生命期。
|
||||
|
||||
:marked
|
||||
The *History* log demonstrates that messages travel in both directions between the parent `MissionControlComponent` and the `AstronautComponent` children, facilitated by the service:
|
||||
|
@ -9,7 +9,7 @@ include ../_util-fns
|
||||
We identify those files with a URL in the `templateUrl` and `styleUrls` properties of the `@Component` metadata
|
||||
as seen here:
|
||||
|
||||
我们的组件通常都是引用外部的模板和样式表文件。
|
||||
组件通常都是引用外部的模板和样式表文件。
|
||||
我们在`@Component`的元数据中通过`templateUrl`和`styleUrls`属性来标识出它们的位置:
|
||||
|
||||
+makeExample('cb-component-relative-paths/ts/app/some.component.ts','absolute-config')(format='.')
|
||||
@ -35,7 +35,7 @@ include ../_util-fns
|
||||
It would be much easier to write and maintain our application components if we could specify template and style locations
|
||||
*relative* to their component class file.
|
||||
|
||||
如果我们能用*相对*于组件类文件的路径来指定模板和样式表的位置,那么编写和维护组件就会变得容易得多。
|
||||
如果能用*相对*于组件类文件的路径来指定模板和样式表的位置,那么编写和维护组件就会变得容易得多。
|
||||
|
||||
*We can!*
|
||||
|
||||
@ -47,7 +47,7 @@ include ../_util-fns
|
||||
with a suitable package loader such as `systemjs` or `webpack`.
|
||||
Learn why [below](#why-default).
|
||||
|
||||
如果把应用构建成`commonjs`模块,并用一个合适的包加载器(比如`systemjs`或`webpack`)加载那些模块,我们就可以用相对路径。
|
||||
如果把应用构建成`commonjs`模块,并用一个合适的包加载器(比如`systemjs`或`webpack`)加载那些模块,就可以用相对路径。
|
||||
[在下方](#why-default)可以学到原理。
|
||||
|
||||
The Angular 2 CLI uses these technologies and defaults to the
|
||||
@ -66,7 +66,7 @@ include ../_util-fns
|
||||
Our goal is to specify template and style URLs *relative* to their component class files,
|
||||
hence the term ***component-relative path***.
|
||||
|
||||
我们的目标把模板和样式表的URL指定为*相对*于组件类的路径,因此得名***组件相对路径***。
|
||||
目标是把模板和样式表的URL指定为*相对*于组件类的路径,因此得名***组件相对路径***。
|
||||
|
||||
The key to success is following a convention that puts related component files in well-known locations.
|
||||
|
||||
@ -76,8 +76,8 @@ include ../_util-fns
|
||||
companion component class files.
|
||||
Here we see the three files for `SomeComponent` sitting next to each other in the `app` folder.
|
||||
|
||||
我们建议把组件的模板和组件特有的样式表文件作为组件类文件的“兄弟”。
|
||||
这里我们看到在`app`目录下依次有`SomeComponent`的三个文件。
|
||||
建议把组件的模板和组件特有的样式表文件作为组件类文件的“兄弟”。
|
||||
这里在`app`目录下依次有`SomeComponent`的三个文件。
|
||||
|
||||
.filetree
|
||||
.file app
|
||||
@ -90,7 +90,7 @@ include ../_util-fns
|
||||
We'll have more files and folders — and greater folder depth — as our application grows.
|
||||
We'll be fine as long as the component files travel together as the inseparable siblings they are.
|
||||
|
||||
当应用规模增长后,我们还会有更多的文件和目录,目录深度也会增加。
|
||||
当应用规模增长后,还会有更多的文件和目录,目录深度也会增加。
|
||||
如果组件的所有文件总是像形影不离的兄弟那样共进退,那该多好啊!
|
||||
|
||||
### Set the *moduleId*
|
||||
@ -99,13 +99,13 @@ include ../_util-fns
|
||||
Having adopted this file structure convention, we can specify locations of the template and style files
|
||||
relative to the component class file simply by setting the `moduleId` property of the `@Component` metadata like this
|
||||
|
||||
采用这种文件结构约定,我们可以为模板和样式表文件指定相对于组件类文件的位置 —— 只要简单的在`@Component`元数据中设置`moduleId`属性就可以了,就像这样:
|
||||
采用这种文件结构约定,可以为模板和样式表文件指定相对于组件类文件的位置 —— 只要简单的在`@Component`元数据中设置`moduleId`属性就可以了,就像这样:
|
||||
|
||||
+makeExample('cb-component-relative-paths/ts/app/some.component.ts','module-id')(format='.')
|
||||
:marked
|
||||
We strip the `app/` base path from the `templateUrl` and `styleUrls`. The result looks like this:
|
||||
|
||||
我们从`templateUrl`和`styleUrls`中把基准路径`app/`去掉了。结果是这样的:
|
||||
从`templateUrl`和`styleUrls`中把基准路径`app/`去掉了。结果是这样的:
|
||||
|
||||
+makeExample('cb-component-relative-paths/ts/app/some.component.ts','relative-config')(format='.')
|
||||
|
||||
@ -173,8 +173,8 @@ a#why-default
|
||||
|
||||
因为如果没有开发人员的帮助,组件的位置是检测不到的。
|
||||
Angular应用可能被用多种方式加载:SystemJS包、CommonJS包等等。
|
||||
我们可能会用几种格式之一来生成模块。
|
||||
我们甚至可能完全没有写成模块化代码。
|
||||
用来生成模块的格式可以是任何格式。
|
||||
甚至可能完全没有写成模块化代码。
|
||||
|
||||
With this diversity of packaging and module load strategies,
|
||||
it's not possible for Angular to know with certainty where these files reside at runtime.
|
||||
@ -195,8 +195,8 @@ a#why-default
|
||||
know that the semi-global `module.id` variable is available and contains
|
||||
the absolute URL of the component class module file.
|
||||
|
||||
但是,*如果*我们遵循了建议的指导原则,用`commonjs`格式编写模块,并使用一个*不错的*模块加载器,
|
||||
然后,我们就知道,有一个可用的半全局变量`module.id`,它包含组件类模块文件的绝对URL。
|
||||
但是,*如果*遵循建议的指导原则,用`commonjs`格式编写模块,并使用一个*不错的*模块加载器,
|
||||
我们要知道,有一个可用的半全局变量`module.id`,它包含组件类模块文件的绝对URL。
|
||||
|
||||
That knowledge enables us to tell Angular where the *component* file is
|
||||
by setting the `moduleId`:
|
||||
|
@ -176,7 +176,7 @@ include ../_util-fns
|
||||
but (a) aren't conceptually part of the application and (b) that we could change later without
|
||||
altering the essential logic of the application.
|
||||
|
||||
使用外部模块时,如果满足下面两个条件,就应该在引导过程中注册:a)它在概念上不是我们程序的一部分,以及 b)将来我们可能要在不改变主要应用逻辑的情况下更换它。
|
||||
使用外部模块时,如果满足下面两个条件,就应该在引导过程中注册:a)它在概念上不是程序的一部分,以及 b)将来可能要在不改变主要应用逻辑的情况下更换它。
|
||||
|
||||
For example, we might configure the Component Router with different
|
||||
[location strategies](../guide/router.html#location-strategy) based on environmental factors.
|
||||
@ -189,12 +189,12 @@ include ../_util-fns
|
||||
We'll switch to the real backend in production.
|
||||
The application shouldn't know or care one way or the other.
|
||||
|
||||
在开发过程中,可以偷偷把一个假的带样本数据的HTTP后端嵌入进来,以代替对一个远程服务器(可能还不存在)进行http查询。我们在产品发布时再切换到真正的后端。应用程序不用知道也不用管正在跟哪个后端打交道。
|
||||
在开发过程中,可以偷偷把一个假的带样本数据的HTTP后端嵌入进来,以代替对一个远程服务器(可能还不存在)进行http查询。在产品发布时再切换到真正的后端。应用程序不用知道也不用管正在跟哪个后端打交道。
|
||||
|
||||
See both examples in the following `main.ts`
|
||||
where we list their service providers in an array in the second parameter of the `bootstrap` method.
|
||||
|
||||
在下面`main.ts`的两个例子中,在`bootstrap`方法的第二个数组型参数中,我们列出了它们的服务供应商。
|
||||
在下面`main.ts`的两个例子中,在`bootstrap`方法的第二个数组型参数中,列出了它们的服务供应商。
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/main.ts','bootstrap','app/main.ts')(format='.')
|
||||
|
||||
@ -286,7 +286,7 @@ figure.image-display
|
||||
Although we recommend applying `@Injectable` to all service classes, do not feel bound by it.
|
||||
Some developers prefer to add it only where needed and that's a reasonable policy too.
|
||||
|
||||
虽然我们推荐在所有服务中使用`@Injectable()`,但你也不需要一定要这么做。一些开发者就更喜欢在真正需要的地方才添加,这也是一个合理的策略。
|
||||
虽然推荐在所有服务中使用`@Injectable()`,但你也不需要一定要这么做。一些开发者就更喜欢在真正需要的地方才添加,这也是一个合理的策略。
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
@ -328,7 +328,7 @@ figure.image-display
|
||||
That isn't always desirable.
|
||||
Sometimes we want to restrict service availability to a particular region of the application.
|
||||
|
||||
但这不一定总是我们想要的。有时候我们想要把服务的有效性限制到应用程序的一个特定区域。
|
||||
但这不一定总是想要的。有时候我们想要把服务的有效性限制到应用程序的一个特定区域。
|
||||
|
||||
We can limit the scope of an injected service to a *branch* of the application hierarchy
|
||||
by providing that service *at the sub-root component for that branch*.
|
||||
@ -347,7 +347,7 @@ figure.image-display
|
||||
We could also provide the `HeroService` to a *different* component elsewhere in the application.
|
||||
That would result in a *different* instance of the service, living in a *different* injector.
|
||||
|
||||
我们也可以在应用程序别处的*不同的*组件里提供`HeroService`。这样就会导致在*不同*注入器中存在该服务的*不同*实例。
|
||||
也可以在应用程序别处的*不同的*组件里提供`HeroService`。这样就会导致在*不同*注入器中存在该服务的*不同*实例。
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
@ -378,7 +378,7 @@ figure.image-display
|
||||
|
||||
Sometimes we want multiple instances of a service at *the same level of the component hierarchy*.
|
||||
|
||||
在*同一个级别的组件树*里,我们有时需要一个服务的多个实例。
|
||||
在*同一个级别的组件树*里,有时需要一个服务的多个实例。
|
||||
|
||||
A good example is a service that holds state for its companion component instance.
|
||||
We need a separate instance of the service for each component.
|
||||
@ -386,7 +386,7 @@ figure.image-display
|
||||
We call this *sandboxing* because each service and component instance has its own sandbox to play in.
|
||||
|
||||
一个用来保存其伴生组件的实例状态的服务就是个好例子。
|
||||
对每个组件,我们都需要该服务的单独实例。
|
||||
每个组件都需要该服务的单独实例。
|
||||
每个服务有自己的工作状态,与其它组件的服务和状态隔离。我们称作*沙盒化*,因为每个服务和组件实例都在自己的沙盒里运行。
|
||||
|
||||
<a id="hero-bios-component"></a>
|
||||
@ -453,8 +453,8 @@ a(id="qualify-dependency-lookup")
|
||||
used individually or together.
|
||||
|
||||
大部分时候,我们确实*想要*这个行为。
|
||||
但是有时候,我们需要限制这个(依赖)查找逻辑,且/或提供一个缺失的依赖。
|
||||
单独或联合使用`@Host`和`@Optional`限定型装饰器,我们就可以修改Angular的查找行为。
|
||||
但是有时候,需要限制这个(依赖)查找逻辑,且/或提供一个缺失的依赖。
|
||||
单独或联合使用`@Host`和`@Optional`限定型装饰器,就可以修改Angular的查找行为。
|
||||
|
||||
The `@Optional` decorator tells Angular to continue when it can't find the dependency.
|
||||
Angular sets the injection parameter to `null` instead.
|
||||
@ -476,7 +476,7 @@ a(id="qualify-dependency-lookup")
|
||||
|
||||
The `HeroBiosAndContactsComponent` is a revision of the `HeroBiosComponent` that we looked at [above](#hero-bios-component).
|
||||
|
||||
`HeroBiosAndContactsComponent`是[前面](#hero-bios-component)我们见过的`HeroBiosComponent`的修改版。
|
||||
`HeroBiosAndContactsComponent`是[前面](#hero-bios-component)见过的`HeroBiosComponent`的修改版。
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/hero-bios.component.ts','hero-bios-and-contacts','app/hero-bios.component.ts (HeroBiosAndContactsComponent)')
|
||||
:marked
|
||||
@ -504,7 +504,7 @@ figure.image-display
|
||||
:marked
|
||||
Here's the `HeroContactComponent` which demonstrates the qualifying decorators that we're talking about in this section:
|
||||
|
||||
下面的`HeroContactComponent`,示范了我们在本节一直在讨论的限定型装饰器(@Optional和@Host):
|
||||
下面的`HeroContactComponent`,示范了在本节一直在讨论的限定型装饰器(@Optional和@Host):
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/hero-contact.component.ts','component','app/hero-contact.component.ts')
|
||||
:marked
|
||||
@ -518,7 +518,7 @@ figure.image-display
|
||||
we get a reference to the cache service from the parent `HeroBioComponent`.
|
||||
Angular throws if the parent lacks that service, even if a component higher in the component tree happens to have that service.
|
||||
|
||||
`@Host()`函数是`heroCache`属性的装饰器,确保我们从其父组件`HeroBioComponent`得到一个缓存服务。如果该父组件不存在这个服务,Angular就会抛出错误,即使组件树里的再上级有某个组件拥有这个服务,Angular也会抛出错误。
|
||||
`@Host()`函数是`heroCache`属性的装饰器,确保从其父组件`HeroBioComponent`得到一个缓存服务。如果该父组件不存在这个服务,Angular就会抛出错误,即使组件树里的再上级有某个组件拥有这个服务,Angular也会抛出错误。
|
||||
|
||||
A second `@Host()` function decorates the `loggerService` property.
|
||||
We know the only `LoggerService` instance in the app is provided at the `AppComponent` level.
|
||||
@ -530,7 +530,7 @@ figure.image-display
|
||||
Angular would throw an error if we hadn't also decorated the property with the `@Optional()` function.
|
||||
Thanks to `@Optional()`, Angular sets the `loggerService` to null and the rest of the component adapts.
|
||||
|
||||
如果我们没有同时使用`@Optional()`装饰器的话,Angular就会抛出错误。多亏了`@Optional()`,Angular把`loggerService`设置为null,并继续执行组件而不会抛出错误。
|
||||
如果没有同时使用`@Optional()`装饰器的话,Angular就会抛出错误。多亏了`@Optional()`,Angular把`loggerService`设置为null,并继续执行组件而不会抛出错误。
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
@ -550,7 +550,7 @@ figure.image-display
|
||||
until it finds the logger at the `AppComponent` level. The logger logic kicks in and the hero display updates
|
||||
with the gratuitous "!!!", indicating that the logger was found.
|
||||
|
||||
如果我们注释掉`@Host()`装饰器,Angular就会沿着注入器树往上走,直到在`AppComponent`中找到该日志服务。日志服务的逻辑加入进来,更新了英雄的显示信息,这表明确实找到了日志服务。
|
||||
如果注释掉`@Host()`装饰器,Angular就会沿着注入器树往上走,直到在`AppComponent`中找到该日志服务。日志服务的逻辑加入进来,更新了英雄的显示信息,这表明确实找到了日志服务。
|
||||
figure.image-display
|
||||
img(src="/resources/images/cookbooks/dependency-injection/hero-bio-contact-no-host.png" alt="Without @Host")
|
||||
:marked
|
||||
@ -559,7 +559,7 @@ figure.image-display
|
||||
<br>
|
||||
`EXCEPTION: No provider for LoggerService! (HeroContactComponent -> LoggerService)`
|
||||
|
||||
另一方面,如果我们恢复`@Host()`装饰器,注释掉`@Optional`,应用程序就会运行失败,因为它在宿主组件级别找不到需要的日志服务。
|
||||
另一方面,如果恢复`@Host()`装饰器,注释掉`@Optional`,应用程序就会运行失败,因为它在宿主组件级别找不到需要的日志服务。
|
||||
<br>
|
||||
`EXCEPTION: No provider for LoggerService! (HeroContactComponent -> LoggerService)`
|
||||
|
||||
@ -573,7 +573,7 @@ figure.image-display
|
||||
Although we strive to avoid it, many visual effects and 3rd party tools (such as jQuery)
|
||||
require DOM access.
|
||||
|
||||
偶尔,我们可能需要访问一个组件对应的DOM元素。我们尽量避免这样做,但还是有很多视觉效果和第三方工具(比如jQuery)需要访问DOM。
|
||||
偶尔,可能需要访问一个组件对应的DOM元素。尽量避免这样做,但还是有很多视觉效果和第三方工具(比如jQuery)需要访问DOM。
|
||||
|
||||
To illustrate, we've written a simplified version of the `HighlightDirective` from
|
||||
the [Attribute Directives](../guide/attribute-directives.html) chapter.
|
||||
@ -683,7 +683,7 @@ figure.image-display
|
||||
The simple class provider is the most typical by far.
|
||||
We mention the class in the `providers` array and we're done.
|
||||
|
||||
简单的类供应商是最典型的例子。我们只要在`providers`数值里面提到该类就可以了。
|
||||
简单的类供应商是最典型的例子。只要在`providers`数值里面提到该类就可以了。
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/hero-bios.component.ts','class-provider','app/hero-bios.component.ts (类供应商)')(format='.')
|
||||
:marked
|
||||
@ -696,7 +696,7 @@ figure.image-display
|
||||
|
||||
The `HeroOfTheMonthComponent` example demonstrates many of the alternatives and why we need them.
|
||||
|
||||
`HeroOfTheMonthComponent`例子示范了一些备选方案,展示了我们为什么需要它们。
|
||||
`HeroOfTheMonthComponent`例子示范了一些备选方案,展示了为什么需要它们。
|
||||
|
||||
figure.image-display
|
||||
img(src="/resources/images/cookbooks/dependency-injection/hero-of-month.png" alt="Hero of the month" width="300px")
|
||||
@ -765,7 +765,7 @@ a(id='usevalue')
|
||||
Obviously the title string literal is immediately available.
|
||||
The `someHero` variable in this example was set earlier in the file:
|
||||
|
||||
一个*值-供应商*的值必须要*立即*定义。我们不能事后再定义它的值。很显然,标题字符串是立刻可用的。
|
||||
一个*值-供应商*的值必须要*立即*定义。不能事后再定义它的值。很显然,标题字符串是立刻可用的。
|
||||
该例中的`someHero`变量是以前在下面这个文件中定义的:
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','some-hero')
|
||||
@ -802,7 +802,7 @@ a(id='useclass')
|
||||
We wrote it in this long form to de-mystify the preferred short form.
|
||||
|
||||
第一个供应商是*展开了语法糖的*,是一个典型情况的展开。一般来说,被新建的类(`HeroService`)同时也是该供应商的注入令牌。
|
||||
我们这里用完整形态来编写它,来反衬我们更喜欢的缩写形式。
|
||||
这里用完整形态来编写它,来反衬我们更喜欢的缩写形式。
|
||||
|
||||
The second provider substitutes the `DateLoggerService` for the `LoggerService`.
|
||||
The `LoggerService` is already registered at the `AppComponent` level.
|
||||
@ -844,7 +844,7 @@ a(id='useexisting')
|
||||
We want to shrink that API surface to just the two members exposed by the `MinimalLogger` [*class-interface*](#class-interface):
|
||||
|
||||
通过使用别名接口来把一个API变窄,是_一个_很重要的该技巧的使用例子。我们在这里就是为了这个目的使用的别名。
|
||||
想象一下如果`LoggerService`有个很大的API接口(虽然它其实只有三个方法,一个属性),我们通过使用`MinimalLogger`[*类-接口*](#class-interface)别名,就能成功的把这个API接口缩小到只暴露两个成员:
|
||||
想象一下如果`LoggerService`有个很大的API接口(虽然它其实只有三个方法,一个属性),通过使用`MinimalLogger`[*类-接口*](#class-interface)别名,就能成功的把这个API接口缩小到只暴露两个成员:
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/date-logger.service.ts','minimal-logger','app/date-logger.service.ts (MinimalLogger)')(format='.')
|
||||
:marked
|
||||
@ -938,13 +938,13 @@ a(id="tokens")
|
||||
Angular dependency injection is easiest when the provider *token* is a class
|
||||
that is also the type of the returned dependency object (what we usually call the *service*).
|
||||
|
||||
Angular依赖注入当*令牌*是类的时候是最简单的,该类同时也是返回的依赖对象的类型(我们通常直接称之为*服务*)。
|
||||
Angular依赖注入当*令牌*是类的时候是最简单的,该类同时也是返回的依赖对象的类型(通常直接称之为*服务*)。
|
||||
|
||||
But the token doesn't have to be a class and even when it is a class,
|
||||
it doesn't have to be the same type as the returned object.
|
||||
That's the subject of our next section.
|
||||
|
||||
但令牌不一定都是类,就算它是一个类,它也不一定都返回类型相同的对象。这是我们下一节的主题。
|
||||
但令牌不一定都是类,就算它是一个类,它也不一定都返回类型相同的对象。这是下一节的主题。
|
||||
|
||||
<a id="class-interface"></a>
|
||||
### class-interface
|
||||
@ -966,7 +966,7 @@ a(id="tokens")
|
||||
But `LoggerService` doesn't inherit from `MinimalLogger`. *No class* inherits from it.
|
||||
Instead, we use it like an interface.
|
||||
|
||||
我们通常从一个抽象类继承。但`LoggerService`并不继承`MinimalLogger`。*没有类*会继承它。我们只把它当接口来使用。
|
||||
我们通常从一个抽象类继承。但`LoggerService`并不继承`MinimalLogger`。*没有类*会继承它。只把它当接口来使用。
|
||||
|
||||
Look again at the declaration for `DateLoggerService`
|
||||
|
||||
@ -983,13 +983,13 @@ a(id="tokens")
|
||||
The key benefit of a *class-interface* is that we can get the strong-typing of an interface
|
||||
and we can ***use it as a provider token*** in the same manner as a normal class.
|
||||
|
||||
我们称这种用法的类叫做*类-接口*。它关键的好处是:给我们提供了接口的强类型,同时,我们能像正常类一样***把它当做供应商令牌使用***。
|
||||
我们称这种用法的类叫做*类-接口*。它关键的好处是:提供了接口的强类型,能像正常类一样***把它当做供应商令牌使用***。
|
||||
|
||||
A ***class-interface*** should define *only* the members that its consumers are allowed to call.
|
||||
Such a narrowing interface helps decouple the concrete class from its consumers.
|
||||
The `MinimalLogger` defines just two of the `LoggerClass` members.
|
||||
|
||||
***类-接口***应该*只*定义它的消费者允许调用的成员。窄的接口有助于我们解耦该类的具体实现和它的消费者。
|
||||
***类-接口***应该*只*定义它的消费者允许调用的成员。窄的接口有助于解耦该类的具体实现和它的消费者。
|
||||
该`MinimalLogger`只定义了两个`LoggerClass`的成员。
|
||||
|
||||
.l-sub-section
|
||||
@ -1003,7 +1003,7 @@ a(id="tokens")
|
||||
They exist only in the TypeScript design space.
|
||||
They disappear after the code is transpiled to JavaScript.
|
||||
|
||||
我们不能把接口当做供应商的令牌,因为接口不是有效的JavaScript对象。
|
||||
不能把接口当做供应商的令牌,因为接口不是有效的JavaScript对象。
|
||||
它们只存在在TypeScript的设计空间里。它们会在被编译为JavaScript之后消失。
|
||||
|
||||
A provider token must be a real JavaScript object of some kind:
|
||||
@ -1024,7 +1024,7 @@ a(id="tokens")
|
||||
:marked
|
||||
It never grows larger no matter how many members we add *as long as they are typed but not implemented*.
|
||||
|
||||
***只要我们不实现它***,不管我们添加多少成员,它永远不会增长大小。
|
||||
***只要不实现它***,不管添加多少成员,它永远不会增长大小。
|
||||
|
||||
a(id='opaque-token')
|
||||
:marked
|
||||
@ -1048,13 +1048,13 @@ a(id='opaque-token')
|
||||
We encountered them twice in the *Hero of the Month* example,
|
||||
in the *title* value provider and in the *runnersUp* factory provider.
|
||||
|
||||
`OpaqueToken`具有这些特征。我们在*Hero of the Month*例子中遇见它们两次,一个是*title*的值,一个是*runnersUp* 工厂供应商。
|
||||
`OpaqueToken`具有这些特征。在*Hero of the Month*例子中遇见它们两次,一个是*title*的值,一个是*runnersUp* 工厂供应商。
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','provide-opaque-token')(format='.')
|
||||
:marked
|
||||
We created the `TITLE` token like this:
|
||||
|
||||
我们这样创建`TITLE`令牌:
|
||||
这样创建`TITLE`令牌:
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','opaque-token')(format='.')
|
||||
|
||||
@ -1071,7 +1071,7 @@ a(id="di-inheritance")
|
||||
we must re-provide and re-inject them in the derived class
|
||||
and then pass them down to the base class through the constructor.
|
||||
|
||||
当编写一个继承自另一个组件的组件时,我们要格外小心。如果基础组件有依赖注入,我们必须要在派生类中重新提供和重新注入它们,并将它们通过构造函数传给基类。
|
||||
当编写一个继承自另一个组件的组件时,要格外小心。如果基础组件有依赖注入,必须要在派生类中重新提供和重新注入它们,并将它们通过构造函数传给基类。
|
||||
|
||||
In this contrived example, `SortedHeroesComponent` inherits from `HeroesBaseComponent`
|
||||
to display a *sorted* list of heroes.
|
||||
@ -1094,7 +1094,7 @@ figure.image-display
|
||||
This rule makes the component safe to construct under test without fear that it will do something dramatic like talk to the server.
|
||||
That's why we call the `HeroService` from within the `ngOnInit` rather than the constructor.
|
||||
|
||||
我们强烈推荐简单的构造函数。它们应该***只***用来初始化变量。这个规则会帮助我们在测试环境中放心的构造组件,以免在构造它们时,无意做了一些非常戏剧化的动作(比如连接服务)。
|
||||
强烈推荐简单的构造函数。它们应该***只***用来初始化变量。这个规则会帮助我们在测试环境中放心的构造组件,以免在构造它们时,无意做了一些非常戏剧化的动作(比如连接服务)。
|
||||
这就是为什么我们要在`ngOnInit`里面调用`HeroService`,而不是在构造函数中。
|
||||
|
||||
We explain the mysterious `afterGetHeroes` below.
|
||||
@ -1115,7 +1115,7 @@ figure.image-display
|
||||
We must provide the `HeroService` again for *this* component,
|
||||
then pass it down to the base class inside the constructor.
|
||||
|
||||
可惜,Angular不能直接在基类里直接注入`HeroService`。我们必须在*这个*组件里再次提供`HeroService`,然后通过构造函数传给基类。
|
||||
可惜,Angular不能直接在基类里直接注入`HeroService`。必须在*这个*组件里再次提供`HeroService`,然后通过构造函数传给基类。
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/sorted-heroes.component.ts','sorted-heroes','app/sorted-heroes.component.ts (SortedHeroesComponent)')
|
||||
:marked
|
||||
@ -1126,7 +1126,7 @@ figure.image-display
|
||||
|
||||
现在,请注意`_afterGetHeroes`方法。
|
||||
我们第一反应是在`SortedHeroesComponent`组件里面建一个`ngOnInit`方法来做排序。但是Angular会先调用*派生*类的`ngOnInit`,后调用基类的`ngOnInit`,
|
||||
所以我们可能在*英雄到达之前*就开始排序。这就产生了一个讨厌的错误。
|
||||
所以可能在*英雄到达之前*就开始排序。这就产生了一个讨厌的错误。
|
||||
|
||||
Overriding the base class's `afterGetHeroes` method solves the problem
|
||||
|
||||
@ -1166,7 +1166,7 @@ a(id="find-parent")
|
||||
But because every component instance is added to an injector's container,
|
||||
we can use Angular dependency injection to reach a parent component.
|
||||
|
||||
但没有公开的API来获取父组件的引用。但是因为每个组件的实例都被加到了依赖注入器的容器中,我们可以使用Angular依赖注入来找到父组件。
|
||||
但没有公开的API来获取父组件的引用。但是因为每个组件的实例都被加到了依赖注入器的容器中,可以使用Angular依赖注入来找到父组件。
|
||||
|
||||
This section describes some techniques for doing that.
|
||||
|
||||
@ -1209,7 +1209,7 @@ a(id='alex')
|
||||
|
||||
What if we do *not* know the concrete parent component class?
|
||||
|
||||
如果我们*不*知道具体的父组件类名怎么办?
|
||||
如果*不*知道具体的父组件类名怎么办?
|
||||
|
||||
A re-usable component might be a child of multiple components.
|
||||
Imagine a component for rendering breaking news about a financial instrument.
|
||||
@ -1222,7 +1222,7 @@ a(id='alex')
|
||||
If we're lucky, they all implement the same base class
|
||||
whose API our `NewsComponent` understands.
|
||||
|
||||
该应用程序可能有多于一打的金融工具组件。如果幸运,它们可能会从同一个基类派生,其API是我们的`NewsComponent`组件所能理解的。
|
||||
该应用程序可能有多于一打的金融工具组件。如果幸运,它们可能会从同一个基类派生,其API是`NewsComponent`组件所能理解的。
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
@ -1236,7 +1236,7 @@ a(id='alex')
|
||||
We're not claiming this is good design.
|
||||
We are asking *can a component inject its parent via the parent's base class*?
|
||||
|
||||
这并不是好的设计。我们的问题是*一个组件是否能通过它父组件的基类来注入它的父组件呢*?
|
||||
这并不是好的设计。问题是*一个组件是否能通过它父组件的基类来注入它的父组件呢*?
|
||||
|
||||
The sample's `CraigComponent` explores this question. [Looking back](#alex)
|
||||
we see that the `Alex` component *extends* (*inherits*) from a class named `Base`.
|
||||
@ -1257,7 +1257,7 @@ a(id='alex')
|
||||
*We cannot inject a parent by its base class.*
|
||||
|
||||
可惜这样不行。[在线例子](/resources/live-examples/cb-dependency-injection/ts/plnkr.html)显示`alex`参数是null。
|
||||
*我们不能通过基类注入父组件*。
|
||||
*不能通过基类注入父组件*。
|
||||
|
||||
<a id="class-interface-parent"></a>
|
||||
### Find a parent by its class-interface
|
||||
@ -1266,7 +1266,7 @@ a(id='alex')
|
||||
|
||||
We can find a parent component with a [class-interface](#class-interface).
|
||||
|
||||
我们可以通过[类-接口](#class-interface)找到一个父组件。
|
||||
可以通过[类-接口](#class-interface)找到一个父组件。
|
||||
|
||||
The parent must cooperate by providing an *alias* to itself in the name of a *class-interface* token.
|
||||
|
||||
@ -1275,7 +1275,7 @@ a(id='alex')
|
||||
Recall that Angular always adds a component instance to its own injector;
|
||||
that's why we could inject *Alex* into *Carol* [earlier](#known-parent).
|
||||
|
||||
请记住Angular总是从它自己的注入器添加一个组件实例;这就是为什么在[之前](#known-parent)我们可以*Alex*注入到*Carol*。
|
||||
请记住Angular总是从它自己的注入器添加一个组件实例;这就是为什么在[之前](#known-parent)可以*Alex*注入到*Carol*。
|
||||
|
||||
We write an [*alias provider*](#useexisting) — a `provide` object literal with a `useExisting` definition —
|
||||
that creates an *alternative* way to inject the same component instance
|
||||
@ -1290,11 +1290,11 @@ a(id="alex-providers")
|
||||
[Parent](#parent-token) is the provider's *class-interface* token.
|
||||
The [*forwardRef*](#forwardref) breaks the circular reference we just created by having the `AlexComponent` refer to itself.
|
||||
|
||||
[Parent](#parent-token)是该供应商的*类-接口*令牌。`AlexComponent`引用了自身,造成循环引用,我们使用[*forwardRef*](#forwardRef)打破了该循环。
|
||||
[Parent](#parent-token)是该供应商的*类-接口*令牌。`AlexComponent`引用了自身,造成循环引用,使用[*forwardRef*](#forwardRef)打破了该循环。
|
||||
|
||||
*Carol*, the third of *Alex*'s child components, injects the parent into its `parent` parameter, the same way we've done it before:
|
||||
|
||||
*Carol*,*Alex*的第三个子组件,把父级注入到了自己的`parent`参数,和我们之前做的一样:
|
||||
*Carol*,*Alex*的第三个子组件,把父级注入到了自己的`parent`参数,和之前做的一样:
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','carol-class','parent-finder.component.ts (CarolComponent class)')(format='.')
|
||||
:marked
|
||||
@ -1332,7 +1332,7 @@ a(id="parent-tree")
|
||||
If we're going to keep writing [*alias providers*](#useexisting) like this we should create a [helper function](#provideparent).
|
||||
|
||||
*Barry*的`providers`数组看起来很像[*Alex*的那个](#alex-providers).
|
||||
如果我们准备一直像这样编写[*别名供应商*](#useexisting)的话,我们应该建立一个[帮助函数](#provideparent)。
|
||||
如果准备一直像这样编写[*别名供应商*](#useexisting)的话,我们应该建立一个[帮助函数](#provideparent)。
|
||||
|
||||
For now, focus on *Barry*'s constructor:
|
||||
|
||||
@ -1359,7 +1359,7 @@ a(id="parent-tree")
|
||||
|
||||
2. Angular throws a cyclic dependency error if we omit the `@SkipSelf` decorator.
|
||||
|
||||
2. 如果我们没写`@SkipSelf`装饰器的话,Angular就会抛出一个循环依赖错误。
|
||||
2. 如果没写`@SkipSelf`装饰器的话,Angular就会抛出一个循环依赖错误。
|
||||
|
||||
`Cannot instantiate cyclic dependency! (BethComponent -> Parent -> BethComponent)`
|
||||
|
||||
@ -1430,20 +1430,20 @@ a(id="provideparent")
|
||||
:marked
|
||||
We can extract that logic into a helper function like this:
|
||||
|
||||
我们可以像这样把该逻辑抽取到一个助手函数里:
|
||||
可以像这样把该逻辑抽取到一个助手函数里:
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','provide-the-parent')(format='.')
|
||||
:marked
|
||||
Now we can add a simpler, more meaningful parent provider to our components:
|
||||
|
||||
现在就可以为我们的组件添加一个更简单、直观的父级供应商了:
|
||||
现在就可以为组件添加一个更简单、直观的父级供应商了:
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','alice-providers')(format='.')
|
||||
:marked
|
||||
We can do better. The current version of the helper function can only alias the `Parent` *class-interface*.
|
||||
Our application might have a variety of parent types, each with its own *class-interface* token.
|
||||
|
||||
我们可以做得更好。当前版本的助手函数只能为`Parent`*类-接口*提供别名。我们的应用程序可能有很多类型的父组件,每个父组件有自己的*类-接口*令牌。
|
||||
我们可以做得更好。当前版本的助手函数只能为`Parent`*类-接口*提供别名。应用程序可能有很多类型的父组件,每个父组件有自己的*类-接口*令牌。
|
||||
|
||||
Here's a revised version that defaults to `parent` but also accepts an optional second parameter for a different parent *class-interface*.
|
||||
|
||||
@ -1453,7 +1453,7 @@ a(id="provideparent")
|
||||
:marked
|
||||
And here's how we could use it with a different parent type:
|
||||
|
||||
下面的代码演示了我们要如何使它添加一个不同类型的父级:
|
||||
下面的代码演示了如何使它添加一个不同类型的父级:
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','beth-providers')(format='.')
|
||||
:marked
|
||||
@ -1468,7 +1468,7 @@ a(id="forwardref")
|
||||
The order of class declaration matters in TypeScript.
|
||||
We can't refer directly to a class until it's been defined.
|
||||
|
||||
在TypeScript里面,类声明的顺序是很重要的。如果一个类尚未定义,我们就不能引用它。
|
||||
在TypeScript里面,类声明的顺序是很重要的。如果一个类尚未定义,就不能引用它。
|
||||
|
||||
This isn't usually a problem, especially if we adhere to the recommended *one class per file* rule.
|
||||
But sometimes circular references are unavoidable.
|
||||
@ -1484,7 +1484,7 @@ a(id="forwardref")
|
||||
|
||||
The *Parent Finder* sample is full of circular class references that are impossible to break.
|
||||
|
||||
这个*父组件查找器*例子里,到处都是我们无法打破的类循环引用。
|
||||
这个*父组件查找器*例子里,到处都是无法打破的类循环引用。
|
||||
|
||||
In the [*Alex/Cathy* example](#known-parent) above:
|
||||
|
||||
@ -1502,7 +1502,7 @@ a(id="forwardref")
|
||||
|
||||
*Alex* refers to *Cathy* and *Cathy* refers to *Alex*. We're stuck. We must define one of them first.
|
||||
|
||||
*Alex* 引用了*Cathy*,同时,*Cathy*引用了*Alex*。我们被卡住了。我们必须要先定义它们中的一个。
|
||||
*Alex* 引用了*Cathy*,同时,*Cathy*引用了*Alex*。我们被卡住了。必须要先定义它们中的一个。
|
||||
|
||||
We defined *Alex* first and built its `C_DIRECTIVES` array with a forward reference to *Cathy*:
|
||||
|
||||
@ -1521,7 +1521,7 @@ a(id="forwardref")
|
||||
while we can add `forwardRef(CathyComponent)` to *Alex*'s `directives` array,
|
||||
we can't write `public alex: forwardRef(AlexComponent))` in *Cathy*'s constructor.
|
||||
|
||||
我们*只能*先定义*Alex*,因为我们可以添加`forwardRef(CathyComponent)`到*Alex*的`Directives`数组里面,但是我们不能在*Cathy*的构造函数里面使用`public alex: forwardRef(AlexComponent))`。
|
||||
*只能*先定义*Alex*,因为我们可以添加`forwardRef(CathyComponent)`到*Alex*的`Directives`数组里面,但是不能在*Cathy*的构造函数里面使用`public alex: forwardRef(AlexComponent))`。
|
||||
|
||||
:marked
|
||||
We face a similar dilemma when a class makes *a reference to itself*
|
||||
|
@ -93,7 +93,7 @@ include _util-fns
|
||||
:marked
|
||||
We can add a barrel to the `heroes` folder (called `index` by convention) that exports all of these items:
|
||||
|
||||
我们可以在`heroes`目录下添加一个封装桶(按规约叫做`index`),它导出所有这三条:
|
||||
在`heroes`目录下添加一个封装桶(按规约叫做`index`),它导出所有这三条:
|
||||
code-example(format='').
|
||||
export * from './hero.model.ts'; // re-export all of its exports
|
||||
export * from './hero.service.ts'; // re-export all of its exports
|
||||
@ -112,7 +112,7 @@ include _util-fns
|
||||
:marked
|
||||
That's why we can write this:
|
||||
|
||||
这就是为什么我们可以这样写的原因:
|
||||
这就是为什么可以这样写的原因:
|
||||
+makeExample('../docs/_fragments/quickstart/ts/app/app.component.ts', 'import')(format=".")
|
||||
// #docregion b-c
|
||||
|
||||
@ -143,7 +143,7 @@ include _util-fns
|
||||
and optionally registers service [providers](#provider) with the
|
||||
[dependency injection system](#dependency-injection).
|
||||
|
||||
我们通过一个名叫`bootstrap`的方法来引导Angular应用程序。这个`bootstrap`方法会识别应用程序的顶级“根”[组件(Component)](#component),
|
||||
通过一个名叫`bootstrap`的方法来引导Angular应用程序。这个`bootstrap`方法会识别应用程序的顶级“根”[组件(Component)](#component),
|
||||
并可能通过[依赖注入体系(Dependency Injection System)](#dependency-injection)注册服务的[供应商(Provider)](#provider)。
|
||||
|
||||
One can bootstrap multiple apps in the same `index.html`, each with its own top level root.
|
||||
@ -169,8 +169,8 @@ include _util-fns
|
||||
This form is also known as **lower camel case**, to distinguish it from **upper camel case** which we call [PascalCase](#pascalcase).
|
||||
When we write "camelCase" in this documentation we always mean *lower camel case*.
|
||||
|
||||
这种形式也被叫做**小驼峰式命名法(lower camel case)**,以区分于**大驼峰式命名法**(我们也叫[Pascal命名法(PascalCase)](#pascalcase))。
|
||||
当我们在文档中提到“驼峰式命名法(camelCase)”的时候,所指的都是小驼峰命名法。
|
||||
这种形式也被叫做**小驼峰式命名法(lower camel case)**,以区分于**大驼峰式命名法**(也叫[Pascal命名法(PascalCase)](#pascalcase))。
|
||||
在文档中提到“驼峰式命名法(camelCase)”的时候,我们所指的都是小驼峰命名法。
|
||||
|
||||
:marked
|
||||
## Component
|
||||
@ -237,13 +237,13 @@ include _util-fns
|
||||
event listeners, pull changed values from the screen, and
|
||||
update application data values ... all by hand.
|
||||
|
||||
我们当然也可以自己处理这些操作:将数据显示到HTML网页,添加事件监听器,从屏幕获取数据变化,然后更新数据等等……
|
||||
当然也可以自己处理这些操作:将数据显示到HTML网页,添加事件监听器,从屏幕获取数据变化,然后更新数据等等……
|
||||
|
||||
Or we could declare the relationship between an HTML widget
|
||||
and an application data source ... and let a data binding
|
||||
framework handle the details.
|
||||
|
||||
或者,我们也可以声明HTML小部件和数据源的关系……,让一个数据绑定框架来处理所有细节。
|
||||
或者,也可以声明HTML小部件和数据源的关系……,让一个数据绑定框架来处理所有细节。
|
||||
|
||||
Data Binding is that second approach. Angular has a rich
|
||||
data binding framework with a variety of data binding
|
||||
@ -291,7 +291,7 @@ include _util-fns
|
||||
We apply a decorator by positioning it
|
||||
immediately above or to the left of the thing it decorates.
|
||||
|
||||
我们应用装饰器的方法是把装饰器放到被装饰对象的上面或左边。
|
||||
应用装饰器的方法是把装饰器放到被装饰对象的上面或左边。
|
||||
|
||||
Angular has its own set of decorators to help it interoperate with our application parts.
|
||||
Here is an example of a `@Component` decorator that identifies a
|
||||
@ -348,14 +348,14 @@ include _util-fns
|
||||
part "A" relies on another part "B", we say that "A" depends on "B" and
|
||||
that "B" is a dependency of "A".
|
||||
|
||||
这些小部件通常会依赖其它小部件。一个Angular[组件(Component)](#component)可能依赖一个“服务”部件来获取数据或处理运算。当部件A要靠另一个部件B才能工作,我们就说A“依赖于”B,B是A的“依赖”。
|
||||
这些小部件通常会依赖其它小部件。一个Angular[组件(Component)](#component)可能依赖一个“服务”部件来获取数据或处理运算。如果部件A要靠另一个部件B才能工作,那么A“依赖于”B,B是A的“依赖”。
|
||||
|
||||
We can ask a "Dependency Injection System" to create "A"
|
||||
for us and handle all the dependencies.
|
||||
If "A" needs "B" and "B" needs "C", the system resolves that chain of dependencies
|
||||
and returns a fully prepared instance of "A".
|
||||
|
||||
我们可以要求“依赖注入系统”为我们创建一个部件A并处理所有A的“依赖”。如果A需要B,B需要C,这个系统便解析这个依赖链,给我们返回一个完全准备好的A实例。
|
||||
我们可以要求“依赖注入系统”为我们创建一个部件A并处理所有A的“依赖”。如果A需要B,B需要C,这个系统便解析这个依赖链,返回一个完全准备好的A实例。
|
||||
|
||||
Angular provides and relies upon its own sophisticated
|
||||
[Dependency Injection](dependency-injection.html) system
|
||||
@ -375,7 +375,7 @@ include _util-fns
|
||||
the value associated with the token for the `Foo` class, typically an instance of `Foo` itself.
|
||||
|
||||
令牌是一个Angular中的类型(`OpaqueToken`)。我们很少需要直接接触令牌。绝大多数类方法都接受类名(`Foo`)或字符串("foo"),Angular会把这些类名称和字符串转换成令牌。
|
||||
当我们调用`injector.get(Foo)`时,注入器返回用`Foo`类生成的令牌所对应的依赖值,该依赖值通常是`Foo`类的实例。
|
||||
当调用`injector.get(Foo)`时,注入器返回用`Foo`类生成的令牌所对应的依赖值,该依赖值通常是`Foo`类的实例。
|
||||
|
||||
Angular makes similar requests internally during many of its operations
|
||||
as when it creates a [`Component`](#AppComponent) for display.
|
||||
@ -664,7 +664,7 @@ include _util-fns
|
||||
In general, we assemble our application from many modules, both the ones we write ourselves
|
||||
and the ones we acquire from others.
|
||||
|
||||
一般来说,我们用模块来组装我们的应用程序,这些模块包含我们自己编写的模块和从其它地方获取的模块。
|
||||
一般来说,我们用模块来组装应用程序,这些模块包含我们自己编写的模块和从其它地方获取的模块。
|
||||
|
||||
A typical module is a cohesive block of code dedicated to a single purpose.
|
||||
|
||||
@ -758,8 +758,8 @@ include _util-fns
|
||||
to associate the pipe function with a name. We then can use that
|
||||
name in our HTML to declaratively transform values on screen.
|
||||
|
||||
Angular的管道是一个函数,用于把输入值转换成输出值以供[视图(View)](#view)显示。我们使用`#{atSym}Pipe`!{decoratorCn}来把管道函数关联到它的名字上。
|
||||
然后,我们就可以在HTML中用它的名字来声明该如何把输入值转换为显示值了。
|
||||
Angular的管道是一个函数,用于把输入值转换成输出值以供[视图(View)](#view)显示。使用`#{atSym}Pipe`!{decoratorCn}来把管道函数关联到它的名字上。
|
||||
然后,就可以在HTML中用它的名字来声明该如何把输入值转换为显示值了。
|
||||
|
||||
Here's an example that uses the built-in `currency` pipe to display
|
||||
a numeric value in the local currency.
|
||||
@ -859,7 +859,7 @@ include _util-fns
|
||||
The only difference, from a consumer perspective,
|
||||
is that the package name begins with the Angular *scope name*, `@angular`.
|
||||
|
||||
我们使用和导入*普通*包相同的方式导入范围化包。
|
||||
使用和导入*普通*包相同的方式导入范围化包。
|
||||
从消费者的视角看,唯一的不同是那些包的名字是用Angular的*范围名*`@angular`开头儿的。
|
||||
|
||||
+makeExample('../docs/_fragments/architecture/ts/app/app.component.ts', 'import')(format=".")
|
||||
@ -899,7 +899,7 @@ include _util-fns
|
||||
|
||||
We write templates in a special [Template Syntax](/docs/ts/latest/guide/template-syntax.html).
|
||||
|
||||
我们使用特殊的[模板语法](/docs/ts/latest/guide/template-syntax.html)来编写模板。
|
||||
使用特殊的[模板语法](/docs/ts/latest/guide/template-syntax.html)来编写模板。
|
||||
|
||||
:marked
|
||||
## Template Expression
|
||||
@ -937,7 +937,7 @@ include _util-fns
|
||||
code completion, refactoring, and intelligent search). Many code editors
|
||||
and IDEs support TypeScript either natively or with plugins.
|
||||
|
||||
TypeScript还以它的可选类型系统而著称。该类型系统给我们提供了编译期类型检查和强大的工具支持(比如“Intellisense”, 自动代码补齐,重构和智能搜索等)。许多程序编辑器和开发环境都自带了TypeScript支持或通过插件提供支持。
|
||||
TypeScript还以它的可选类型系统而著称。该类型系统提供了编译期类型检查和强大的工具支持(比如“Intellisense”, 自动代码补齐,重构和智能搜索等)。许多程序编辑器和开发环境都自带了TypeScript支持或通过插件提供支持。
|
||||
|
||||
TypeScript is the preferred language for Angular 2 development although
|
||||
we are welcome to write in other JavaScript dialects such as [ES5](#es5).
|
||||
@ -974,7 +974,7 @@ include _util-fns
|
||||
find it convenient to refer to a component as a view.
|
||||
|
||||
Angular在一个或多个[指令(Directive)](#directive)的控制下渲染视图,尤其是[组件(Component)](#component)型指令及其[模板(Template)](#template)。
|
||||
组件扮演着非常重要的角色,甚至我们经常会为了方便而直接用“视图”作为组件的代名词。
|
||||
组件扮演着非常重要的角色,我们甚至经常会为了方便, 直接用“视图”作为组件的代名词。
|
||||
|
||||
Views often contain other views and any view might be loaded and unloaded
|
||||
dynamically as the user navigates through the application, typically
|
||||
@ -1015,7 +1015,7 @@ include _util-fns
|
||||
asynchronous events by checking for data changes and updating
|
||||
the information it displays via [data binding](#data-binding).
|
||||
|
||||
Angular会在一个区域中运行我们的应用程序,在这个区域中,它可以对异步事件做出反应,可以通过检查数据变更、利用[数据绑定(Data Binding)](#data-binding)来更新信息显示。
|
||||
Angular会在一个 Zone 区域中运行应用程序,在这个区域中,它可以对异步事件做出反应,可以通过检查数据变更、利用[数据绑定(Data Binding)](#data-binding)来更新信息显示。
|
||||
|
||||
Learn more about zones in this
|
||||
[Brian Ford video](https://www.youtube.com/watch?v=3IqtmUscE_U).
|
||||
|
@ -94,7 +94,7 @@ block download-source
|
||||
[download the QuickStart source](https://github.com/angular/quickstart/blob/master/README.md)
|
||||
from github and follow its brief instructions.
|
||||
|
||||
如果不想跟着这里的操作指南来一步步儿做,我们也可以从github[下载“快速起步”的源码](https://github.com/angular/quickstart/blob/master/README.md),这样只要注意那些操作要点就行了。
|
||||
如果不想跟着这里的操作指南来一步步儿做,可以从github[下载“快速起步”的源码](https://github.com/angular/quickstart/blob/master/README.md),这样只要注意那些操作要点就行了。
|
||||
|
||||
.l-main-section
|
||||
button(class="verbose off md-primary md-button md-ink-ripple", type="button", onclick="verbose(false)").
|
||||
@ -121,7 +121,7 @@ button(class="verbose on md-primary md-button md-ink-ripple", type="button", onc
|
||||
:marked
|
||||
We'll see many code blocks as we build the QuickStart app. They're all easy to copy and paste:
|
||||
|
||||
当我们构建这个“快速起步”应用时,会看到很多代码块儿。它们都很方便拷贝和粘贴:
|
||||
当构建这个“快速起步”应用时,我们会看到很多代码块。它们都很方便拷贝和粘贴:
|
||||
code-example(format="nocode").
|
||||
点击右侧的图标,来把代码片段拷贝到剪贴板 ==>
|
||||
|
||||
@ -205,7 +205,7 @@ block install-packages
|
||||
We install the packages listed in `package.json` using `npm`. Enter the
|
||||
following command in a terminal window (command window in Windows):
|
||||
|
||||
我们使用`npm`命令来安装`package.json`中列出的依赖包。请在终端窗口(或Windows的cmd窗口)中输入下列命令:
|
||||
使用`npm`命令来安装`package.json`中列出的依赖包。请在终端窗口(或Windows的cmd窗口)中输入下列命令:
|
||||
|
||||
code-example(language="sh").
|
||||
npm install
|
||||
@ -240,7 +240,7 @@ block install-packages
|
||||
If the recompile fails, the package recovers (typically with a pre-built version)
|
||||
and everything works.
|
||||
|
||||
我们通常会在一系列`gyp ERR!`消息后面看到一个`npm WARN`消息。直接忽略即可。
|
||||
通常会在一系列`gyp ERR!`消息后面看到一个`npm WARN`消息。忽略即可。
|
||||
有些依赖包可能会尝试用`node-gyp`重新编译它自己。
|
||||
如果重新编译失败了,这个包就会自行恢复(通常是下载一个预编译版本),最终不会影响使用。
|
||||
|
||||
@ -251,7 +251,7 @@ block install-packages
|
||||
.l-verbose-section
|
||||
:marked
|
||||
#### Adding the libraries and packages we need with *npm*
|
||||
#### 用*npm*添加我们需要的库和依赖包
|
||||
#### 用*npm*添加需要的库和依赖包
|
||||
|
||||
Angular application developers rely on the _[npm](https://docs.npmjs.com)_
|
||||
package manager to install the libraries and packages their apps require.
|
||||
@ -267,14 +267,14 @@ block install-packages
|
||||
#### 有用的脚本
|
||||
We've included a number of npm scripts in our suggested `package.json` to handle common development tasks:
|
||||
|
||||
在我们推荐的这个`package.json`中,包含了几个npm脚本,用来处理常用的开发任务:
|
||||
在推荐的这个`package.json`中,包含了几个npm脚本,用来处理常用的开发任务:
|
||||
+makeJson('quickstart/ts/package.1.json',{ paths: 'scripts'}, 'package.json (脚本)')(format=".")
|
||||
|
||||
:marked
|
||||
We execute most npm scripts in the following way: `npm run` followed by a *script-name*.
|
||||
Some commands (such as `start`) don't require the `run` keyword.
|
||||
|
||||
我们执行大多数npm脚本的方式都差不多:`npm run`后面跟着*脚本名*。
|
||||
执行大多数npm脚本的方式都差不多:`npm run`后面跟着*脚本名*。
|
||||
有些命令(比如`start`)不需要`run`关键字。
|
||||
|
||||
Here's what these scripts do:
|
||||
@ -310,7 +310,7 @@ block install-packages
|
||||
:marked
|
||||
**We're all set.** Let's write some code.
|
||||
|
||||
**全部设置完了。** 我们来写点代码吧。
|
||||
**全部设置完了。** 来写点代码吧。
|
||||
|
||||
.l-main-section
|
||||
h2#root-component Step 2: Our first Angular component
|
||||
@ -318,7 +318,7 @@ h2#root-component 步骤2:我们的第一个Angular组件
|
||||
:marked
|
||||
Let's create a folder to hold our application and add a super-simple Angular component.
|
||||
|
||||
我们来创建一个文件夹,用于保存我们的应用,并且添加一个超级简单的Angular组件。
|
||||
创建一个文件夹,用于保存应用程序,并且添加一个超级简单的Angular组件。
|
||||
|
||||
**Create #{_an} #{_appDir} subfolder** off the project root directory:
|
||||
|
||||
@ -353,11 +353,11 @@ p.
|
||||
This QuickStart has only one, extremely simple component.
|
||||
But it has the essential structure of every component we'll ever write:
|
||||
|
||||
这个“快速起步”只有一个非常简单的组件,但麻雀虽小,五脏俱全 —— 它具备了我们将来写的组件的基本结构。
|
||||
这个“快速起步”只有一个非常简单的组件,但麻雀虽小,五脏俱全 —— 它具备了将来写的组件的基本结构。
|
||||
|
||||
* One or more [import](#component-import)
|
||||
statements to reference the things we need.
|
||||
* 一个或多个[import](#component-import)语句来引入我们所需的文件。
|
||||
* 一个或多个[import](#component-import)语句来引入所需的文件。
|
||||
* A [@Component #{_decorator}](#component-decorator)
|
||||
that tells Angular what template to use and how to create the component.
|
||||
* 一个[@Component #{_decoratorCn}](#component-decorator)
|
||||
@ -377,14 +377,14 @@ p.
|
||||
each made up of several, related features that we'll use to build our application.
|
||||
|
||||
Angular应用都是模块化的。它们由很多职责明确的文件组成。
|
||||
Angular本身也是模块化的。它包括一系列的库模块,这些模块包括了一系列相关的特性,以便我们可以拿来构建自己的应用。
|
||||
Angular本身也是模块化的。它包括一系列的库模块,这些模块包括了一系列相关的特性,以便拿来构建应用程序。
|
||||
|
||||
When we need something from a module or library, we import it.
|
||||
Here we import the Angular 2 core so that our component code can have access to
|
||||
the `@Component` #{_decorator}.
|
||||
|
||||
当我们需要一个模块中的某些东西时,我们引入(import)它。
|
||||
在这里,我们导入了Angular 2核心库,以便我们的组件代码能够访问`@Component` #{_decoratorCn}。
|
||||
当需要一个模块中的某些东西时,引入(import)它。
|
||||
在这里,我们导入了Angular 2核心库,以便组件代码访问`@Component` #{_decoratorCn}。
|
||||
+makeExcerpt('app/app.component.ts', 'import')
|
||||
|
||||
h3#component-decorator @Component #{_decorator}
|
||||
@ -396,13 +396,13 @@ p.
|
||||
**@** symbol and invoking it with a metadata object, just above the class.
|
||||
|
||||
`Component`是一个*装饰器函数*,它接受一个*元数据对象*作为参数。
|
||||
通过给这个函数加上**@**前缀,我们就可以把这个函数加到组件类上,比如上面这个类。
|
||||
通过给这个函数加上**@**前缀,可以把这个函数加到组件类上,比如上面这个类。
|
||||
:marked
|
||||
`@Component` is #{_a} *#{_decorator}* that allows us to associate *metadata* with the
|
||||
component class.
|
||||
The metadata tells Angular how to create and use this component.
|
||||
|
||||
`@Component` 是一个*#{_decoratorCn}*,它允许我们把*元数据*关联到组件类上。这些元数据会告诉Angular如何创建和使用我们的类。
|
||||
`@Component` 是一个*#{_decoratorCn}*,它把*元数据*关联到组件类上。这些元数据会告诉Angular如何创建和使用组件类。
|
||||
|
||||
+makeExcerpt('app/app.component.ts', 'metadata')
|
||||
|
||||
@ -432,7 +432,7 @@ p.
|
||||
|
||||
>Our template is a single line of HTML announcing "*My First Angular 2 App*".
|
||||
|
||||
>我们的模板中只有一行HTML:“*My First Angular App*”。
|
||||
>模板中只有一行HTML:“*My First Angular App*”。
|
||||
|
||||
>A more advanced template could contain data bindings to component properties
|
||||
and might identify other application compoents which have their own templates.
|
||||
@ -454,14 +454,14 @@ p.
|
||||
we can expand this class with properties and application logic.
|
||||
Our `AppComponent` class is empty because we don't need it to do anything in this QuickStart.
|
||||
|
||||
当我们打算构建一个真实的应用时,可以通过添加属性和应用逻辑来扩展这个类。
|
||||
但我们不需要在这个“快速起步”中做这些事,所以这里的`AppComponent`类是空的。
|
||||
打算构建一个真实的应用时,通过添加属性和应用逻辑来扩展这个类。
|
||||
但不需要在这个“快速起步”中做这些事,所以这里的`AppComponent`类是空的。
|
||||
+ifDocsFor('ts')
|
||||
:marked
|
||||
We **export** `AppComponent` so that we can **import** it elsewhere in our application,
|
||||
as we'll see when we create `main.ts`.
|
||||
|
||||
我们**导出**`AppComponent`,以便我们可以在应用的其它地方**导入**它 —— 比如我们创建`main.ts`时。
|
||||
**导出**`AppComponent`,以便在应用的其它地方**导入**它 —— 比如创建`main.ts`时。
|
||||
.l-main-section
|
||||
h2#main Step 3: Add #[code #[+adjExPath('main.ts')]]
|
||||
h2#main 步骤3:添加#[code #[+adjExPath('main.ts')]]
|
||||
@ -489,7 +489,7 @@ block create-main
|
||||
|
||||
Then we call `bootstrap` with `AppComponent`.
|
||||
|
||||
然后,我们调用`bootstrap`函数,并且把`AppComponent`传进去。
|
||||
然后,调用`bootstrap`函数,并且把`AppComponent`传进去。
|
||||
|
||||
### Bootstrapping is platform-specific
|
||||
### “启动”是平台相关的
|
||||
@ -510,8 +510,8 @@ block create-main
|
||||
These targets require a different kind of bootstrap function that we'd import from a different library.
|
||||
|
||||
但从其它环境中加载组件也是可能的。
|
||||
我们可能通过[Apache Cordova](https://cordova.apache.org/) 或 [NativeScript](https://www.nativescript.org/) 在移动设备中加载它。
|
||||
我们可能希望在服务器中渲染我们的第一个页面来提高启动效率或
|
||||
可能需要通过[Apache Cordova](https://cordova.apache.org/) 或 [NativeScript](https://www.nativescript.org/) 在移动设备中加载它。
|
||||
可能希望在服务器中渲染第一个页面来提高启动效率或
|
||||
让[SEO](http://static.googleusercontent.com/media/www.google.com/en//webmasters/docs/search-engine-optimization-starter-guide.pdf)更加容易。
|
||||
要达成这些目标,我们需要从其它库中引入一个不同类型的`bootstrap`函数。
|
||||
|
||||
@ -537,7 +537,7 @@ block create-main
|
||||
但我们应该用正确的方式组织Angular应用的文件结构。
|
||||
启动App与展现视图是两个相互分离的关注点。
|
||||
把这些关注点混在一起会增加不必要的难度。
|
||||
我们可以通过使用不同的引导器(bootstraper)来在不同的环境中启动`AppComponent`。
|
||||
可以通过使用不同的引导器(bootstraper)来在不同的环境中启动`AppComponent`。
|
||||
测试组件也变得更容易,因为不需要再运行整个程序才能跑测试。
|
||||
让我们多花一点精力来用*“正确的方式”*实现它。
|
||||
|
||||
@ -568,9 +568,9 @@ h2#index 步骤4:添加#[code index.html]
|
||||
1. JavaScript [库](#libraries)
|
||||
2. Configuration file for [SystemJS](#systemjs), and a script
|
||||
where we import and run the `app` module which refers to the `main` file that we just wrote.
|
||||
2. 配置[SystemJS](#systemjs),以便引入和运行我们刚才写的`main`文件。
|
||||
2. 配置[SystemJS](#systemjs),以便引入和运行刚才写的`main`文件。
|
||||
3. The [`<my-app>`](#my-app) tag in the `<body>` which is *where our app lives!*
|
||||
3. `<body>`中的[<my-app>](#my-app)标签是*供我们的应用“生活”的地方。*
|
||||
3. `<body>`中的[<my-app>](#my-app)标签是*供应用程序“生活”的地方。*
|
||||
|
||||
:marked
|
||||
### Libraries
|
||||
@ -584,7 +584,7 @@ h2#index 步骤4:添加#[code index.html]
|
||||
Next are the polyfills for Angular2, `zone.js` and `reflect-metadata`.
|
||||
Then the [SystemJS](#systemjs) library for module loading.
|
||||
|
||||
我们首先引入es6-shim,它会给全局对象window打上补丁,使其支持ES2015(ES6)的必备特性。
|
||||
首先引入es6-shim,它会给全局对象window打上补丁,使其支持ES2015(ES6)的必备特性。
|
||||
然后是Angular 2的polyfills,以及`zone.js`和`reflect-metadata`。
|
||||
然后是用于模块加载的[SystemJS](#systemjs)库。
|
||||
|
||||
@ -592,7 +592,7 @@ h2#index 步骤4:添加#[code index.html]
|
||||
become more concerned about production qualities such as
|
||||
load times and memory footprint.
|
||||
|
||||
等我们变得更有经验、更关心产品质量(如加载时间、内存足迹等),也可以做出不同的选择。
|
||||
等我们变得更有经验、更关心产品质量(如加载时间、内存足迹等)时,也可以做出不同的选择。
|
||||
h3#systemjs SystemJS
|
||||
:marked
|
||||
QuickStart uses <a href="https://github.com/systemjs/systemjs" target="_blank">SystemJS</a>
|
||||
@ -606,20 +606,20 @@ h2#index 步骤4:添加#[code index.html]
|
||||
本“快速起步”使用<a href="https://github.com/systemjs/systemjs" target="_blank">SystemJS</a>来加载应用和库模块。
|
||||
[以前](#add-config-files)我们曾把`systemjs.config.js`文件添加到项目的根目录。
|
||||
还有一些其它候选者也能很好地工作,比如备受推崇的[webpack](guide/webpack.html)。
|
||||
SystemJS是一个好的选择,但要清楚,它只是我们给你的“选择之一”,而不是“首选项”。
|
||||
SystemJS是一个好的选择,但要清楚,它只是“选择之一”,而不是“首选项”。
|
||||
|
||||
All module loaders require configuration and all loader configuration
|
||||
becomes complicated rather quickly as soon as the file structure diversifies and
|
||||
we start thinking about building for production and performance.
|
||||
|
||||
所有loader(模块加载器)都需要配置,并且文件结构很快就会变得多样,
|
||||
loader的配置也会变得复杂,那时候我们就要开始考虑产品构建和性能问题了。
|
||||
loader的配置也会变得复杂,那时候就要开始考虑产品构建和性能问题了。
|
||||
|
||||
We suggest becoming well-versed in the loader of your choice.
|
||||
Learn more about SystemJS configuration
|
||||
<a href="https://github.com/systemjs/systemjs/blob/master/docs/config-api.md" target="_blank">here</a>.
|
||||
|
||||
我们建议你要精通你所选的loader。
|
||||
建议你要精通你所选的loader。
|
||||
要学习如何配置SystemJS的更多知识,参见<a href="https://github.com/systemjs/systemjs/blob/master/docs/config-api.md" target="_blank">这里</a>。
|
||||
|
||||
With those cautions in mind, what are we doing in the
|
||||
@ -628,10 +628,10 @@ h2#index 步骤4:添加#[code index.html]
|
||||
Then, we register all our packages to SystemJS:
|
||||
all the project dependencies and our application package, `app`.
|
||||
|
||||
把这些记在心里,我们再来看看加在“快速起步”中的[`systemjs.config.js`配置文件](#config-files)都做了什么。
|
||||
把这些记在心里,再来看看加在“快速起步”中的[`systemjs.config.js`配置文件](#config-files)都做了什么。
|
||||
首先,创建了一个映射表,来告诉SystemJS当想要引入某些模块的时候,该到哪里去找。
|
||||
然后,我们把自己的所有包注册到SystemJS中:
|
||||
项目的所有外部依赖,以及我们自己的应用包`app`。
|
||||
然后,把自己的所有包注册到SystemJS中:
|
||||
项目的所有外部依赖,以及自己的应用包`app`。
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
@ -653,7 +653,7 @@ h2#index 步骤4:添加#[code index.html]
|
||||
Our QuickStart makes such requests when one of its
|
||||
application TypeScript files has an import statement like this:
|
||||
|
||||
在我们的“快速起步”中,当应用中的一个TypeScript文件有这样的一个导入语句时:
|
||||
在“快速起步”中,当应用中的一个TypeScript文件有这样的一个导入语句时:
|
||||
+makeExcerpt('app/main.ts', 'import')
|
||||
:marked
|
||||
SystemJS就会开始介入。
|
||||
@ -667,7 +667,7 @@ h2#index 步骤4:添加#[code index.html]
|
||||
That makes sense because we transpile TypeScript to JavaScript
|
||||
*before* running the application.
|
||||
|
||||
这是因为我们在运行应用程序*之前*会执行从TypeScript到JavaScript的转译(transpile)。
|
||||
这是因为在运行应用程序*之前*会执行从TypeScript到JavaScript的转译(transpile)。
|
||||
.l-sub-section
|
||||
:marked
|
||||
#### Transpiling in the browser
|
||||
@ -684,11 +684,11 @@ h2#index 步骤4:添加#[code index.html]
|
||||
We strongly recommend transpiling (AKA compiling) to JavaScript during a build phase
|
||||
before running the application for several reasons including:
|
||||
|
||||
我们强烈建议在运行应用之前的build阶段转译(编译)到JavaScript,理由包括:
|
||||
强烈建议在运行应用之前的build阶段转译(编译)到JavaScript,理由包括:
|
||||
|
||||
* We see compiler warnings and errors that are hidden from us in the browser.
|
||||
|
||||
* 我们可以看到编译器的警告和错误,但浏览器中不行。
|
||||
* 可以看到编译器的警告和错误,但浏览器中不行。
|
||||
|
||||
* Precompilation simplifies the module loading process and
|
||||
it's much easier to diagnose problems when this is a separate, external step.
|
||||
@ -702,7 +702,7 @@ h2#index 步骤4:添加#[code index.html]
|
||||
* We iterate development faster because we only recompile changed files.
|
||||
We notice the difference as soon as the app grows beyond a handful of files.
|
||||
|
||||
* 我们的迭代开发会更快,因为我们只需要重新编译那些有变化的文件。当应用程序快速膨胀成一大堆文件时,你会体验到这些差异。
|
||||
* 迭代开发会更快,因为只需要重新编译那些有变化的文件。当应用程序快速膨胀成一大堆文件时,你会体验到这些差异。
|
||||
|
||||
* Precompilation fits into a continuous integration process of build, test, deploy.
|
||||
|
||||
@ -715,8 +715,8 @@ h2#index 步骤4:添加#[code index.html]
|
||||
We also catch and log launch errors to the console.
|
||||
|
||||
`System.import`调用告诉SystemJS引入`main`文件。(`main.js`,从`main.ts`转译而来的,还记得吧?)
|
||||
`main`是我们让Angular启动应用的地方。
|
||||
我们还会把启动过程中的错误捕获并记录到控制台中。
|
||||
`main`是让Angular启动应用的地方。
|
||||
还会把启动过程中的错误捕获并记录到控制台中。
|
||||
|
||||
All other modules are loaded upon request
|
||||
either by an import statement or by Angular itself.
|
||||
@ -732,14 +732,14 @@ h2#index 步骤4:添加#[code index.html]
|
||||
and renders our application's view between those tags.
|
||||
|
||||
当Angular在`main.ts`中调用`bootstrap`函数时,它读取`AppComponent`的元数据,
|
||||
发现选择器是`my-app`,于是它定位到一个元素名为`my-app`的DOM元素,并且把我们的应用加载到这个标签中。
|
||||
发现选择器是`my-app`,于是它定位到一个元素名为`my-app`的DOM元素,并且把应用加载到这个标签中。
|
||||
:marked
|
||||
### Add some style
|
||||
### 添加一些样式
|
||||
Styles aren't essential but they're nice, and `index.html` assumes we have
|
||||
a stylesheet called `styles.css`.
|
||||
|
||||
样式不是必备的,但是它让我们的应用更漂亮。`index.html`假设我们有一个名叫`styles.css`的样式表。
|
||||
样式不是必备的,但是它让应用更漂亮。`index.html`假设有一个名叫`styles.css`的样式表。
|
||||
|
||||
Create a `styles.css` file in the *#{_indexHtmlDir}* folder and start styling, perhaps with the minimal
|
||||
styles shown below. For the full set of master styles used by the documentation samples,
|
||||
@ -807,7 +807,7 @@ block server-watching
|
||||
|
||||
We close the terminal window when we're done to terminate both the compiler and the server.
|
||||
|
||||
当终止了编译器和服务器之后,我们可以关闭terminal窗口。
|
||||
当终止了编译器和服务器之后,可以关闭terminal窗口。
|
||||
.l-main-section
|
||||
:marked
|
||||
# Wrap up
|
||||
@ -864,14 +864,14 @@ block project-files
|
||||
|
||||
Our first application doesn't do much. It's basically "Hello, World" for Angular 2.
|
||||
|
||||
我们的第一个应用没做什么,它只是Angular 2的“Hello, World”。
|
||||
第一个应用没做什么,它只是Angular 2的“Hello, World”。
|
||||
|
||||
We kept it simple in our first pass: we wrote a little Angular component,
|
||||
created a simple `index.html`, and launched with a
|
||||
static file server. That's about all we'd expect to do for a "Hello, World" app.
|
||||
|
||||
我们让自己的Angular 2处女航保持简单:我们写了一个小的Angular组件,添加一些JavaScript库到`index.html`,并且启动一个静态文件服务器。
|
||||
这就是我们想通过“Hello, World”应用去表现的一切。
|
||||
为了让自己的Angular 2处女航保持简单:我们写了一个小的Angular组件,添加一些JavaScript库到`index.html`,并且启动一个静态文件服务器。
|
||||
这就是通过“Hello, World”应用表现的一切。
|
||||
|
||||
**We have greater ambitions!**
|
||||
|
||||
@ -883,8 +883,8 @@ block what-next-ts-overhead
|
||||
We'll likely open `index.html` only if we need to add a library or some css stylesheets.
|
||||
|
||||
好消息是:准备阶段(几乎)已经结束了。
|
||||
我们将来可能只是修改`package.json`来升级依赖库。
|
||||
如果需要添加一些库或一些css样式表,我们可以打开`index.html`。
|
||||
将来可能只是修改`package.json`来升级依赖库。
|
||||
如果需要添加一些库或一些css样式表,可以打开`index.html`。
|
||||
:marked
|
||||
We're about to take the next step and build a small application that
|
||||
demonstrates the great things we can build with Angular 2.
|
||||
|
Loading…
x
Reference in New Issue
Block a user