cookbook - 组件相对路径 初译完毕

cookbook - 1 to 2 初译开始
其它微调
This commit is contained in:
Zhicheng Wang 2016-06-01 18:34:02 +08:00
parent 72efc8f055
commit bfc5c70349
3 changed files with 233 additions and 139 deletions

View File

@ -5,24 +5,29 @@ a(id="top")
This chapter provides a quick reference guide to some of the common Angular 1
syntax and its equivalent in Angular 2.
在Angular 1和Anuglar 2之间有很多不同的概念和语法。
本章提供了一个快速的参考指南指出一些常用的Angular 1语法及其在Angular 2中的等价物。
:marked
**See the Angular 2 syntax in this [live example](/resources/live-examples/cb-a1-a2-quick-reference/ts/plnkr.html)**.
**可到[在线范例](/resources/live-examples/cb-a1-a2-quick-reference/ts/plnkr.html)中查看Angular 2语法**。
## Contents
This chapter covers
* [Template Basics](#template-basics) - binding and local variables
* [Template Directives](#template-directives) - built-in directives `ngIf` and `ngClass`
* [Filters/Pipes](#filters-pipes) - built-in *filters*, known as *pipes* in Angular 2
* [Controllers/Components](#controllers-components) - *controllers* are *components* in Angular 2.
* [Controllers/Components](#controllers-components) - *controllers* are *components* in Angular 2.
Also covers modules.
* [Style Sheets](#style-sheets) - more options for CSS in Angular 2.
* [String date pipe](#string-dates) - a tip for displaying string date values.
.l-main-section
:marked
## Template Basics
@ -33,7 +38,7 @@ a(id="top")
- var top="vertical-align:top"
table(width="100%")
col(width="50%")
col(width="50%")
col(width="50%")
tr
th Angular 1
th Angular 2
@ -47,7 +52,7 @@ table(width="100%")
In Angular 1, an expression in curly braces denotes one-way binding.
This binds the value of the element to a property in the controller
associated with this template.
When using the `controller as` syntax,
the binding is prefixed with the controller alias (`vm`) because we
have to be specific about the source of the binding.
@ -60,7 +65,7 @@ table(width="100%")
This binds the value of the element to a property of the component.
The context of the binding is implied and is always the
associated component, so it needs no reference variable.
For more information see [Template Syntax](../guide/template-syntax.html#interpolation).
tr(style=top)
td
@ -70,7 +75,7 @@ table(width="100%")
<td>{{movie.title | uppercase}}</td>
:marked
To filter output in our templates in Angular 1, we use the pipe character (|) and one or more filters.
In this example, we filter the `title` property to uppercase.
td
:marked
@ -80,7 +85,7 @@ table(width="100%")
In Angular 2, we use similar syntax with the pipe (|) character to filter output, but now we call them **pipes**.
Many (but not all) of the built-in filters from Angular 1 are
built-in pipes in Angular 2.
See the heading [Filters / Pipes](#Pipes) below for more information.
tr(style=top)
td
@ -98,21 +103,21 @@ table(width="100%")
+makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'local')(format="." )
:marked
In Angular 2, we have true template input variables that are explicitly defined using the `let` keyword.
For more information see [ngFor micro-syntax](../guide/template-syntax.html#ngForMicrosyntax).
:marked
[Back to top](#top)
.l-main-section
:marked
## Template Directives
Angular 1 provides over seventy built-in directives for use in our templates.
Many of them are no longer needed in Angular 2 because of its more capable and expressive binding system.
Angular 1 provides over seventy built-in directives for use in our templates.
Many of them are no longer needed in Angular 2 because of its more capable and expressive binding system.
The following are some of the key Angular 1 built-in directives and the equivalent feature in Angular 2.
table(width="100%")
col(width="50%")
col(width="50%")
col(width="50%")
tr
th Angular 1
th Angular 2
@ -121,10 +126,10 @@ table(width="100%")
:marked
### ng-app
code-example.
<body ng-app="movieHunter">
<body ng-app="movieHunter">
:marked
The application startup process is called **bootstrapping**.
Although we can bootstrap an Angular 1 app in code,
many applications bootstrap declaratively with the `ng-app` directive,
giving it the name of the application's module (`movieHunter`).
@ -136,7 +141,7 @@ table(width="100%")
Angular 2 does not have a bootstrap directive.
We always launch the app in code by explicitly calling a bootstrap function
and passing it the name of the application's module (`AppComponent`).
For more information see [Quick Start](../quickstart.html).
tr(style=top)
td
@ -144,32 +149,32 @@ table(width="100%")
### ng-class
code-example(format="").
<div ng-class="{active: isActive}">
<div ng-class="{active: isActive,
<div ng-class="{active: isActive,
shazam: isImportant}">
:marked
In Angular 1, the `ng-class` directive includes/excludes CSS classes
based on an expression. That expression is often a key-value control object with each
key of the object defined as a CSS class name, and each value defined as a template expression
that evaluates to a Boolean value.
In the first example, the `active` class is applied to the element if `isActive` is true.
We can specify multiple classes as shown in the second example.
td
:marked
### ngClass
+makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'ngClass')(format="." )
:marked
In Angular 2, the `ngClass` directive works similarly.
It includes/excludes CSS classes based on an expression.
In Angular 2, the `ngClass` directive works similarly.
It includes/excludes CSS classes based on an expression.
In the first example, the `active` class is applied to the element if `isActive` is true.
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
Angular 2 also has **class binding**, which is a good way to add or remove a single class
as shown in the third example.
For more information see [Template Syntax](../guide/template-syntax.html#other-bindings).
tr(style=top)
@ -181,9 +186,9 @@ table(width="100%")
<button ng-click="vm.toggleImage($event)">
:marked
In Angular 1, the `ng-click` directive allows us to specify custom behavior when an element is clicked.
In the first example, when the button is clicked, the `toggleImage()` method in the controller referenced by the `vm` `controller as` alias is executed.
The second example demonstrates passing in the `$event` object, which provides details about the event
to the controller.
td
@ -191,21 +196,21 @@ table(width="100%")
### bind to the `click` event
+makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'event-binding')(format="." )
:marked
The Angular 1 event-based directives do not exist in Angular 2.
The Angular 1 event-based directives do not exist in Angular 2.
Rather, we define one-way binding from the template view to the component using **event binding**.
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.
In the first example, when the button is clicked, the `toggleImage()` method in the associated component is executed.
The second example demonstrates passing in the `$event` object, which provides details about the event
to the component.
For a list of DOM events, see: https://developer.mozilla.org/en-US/docs/Web/Events.
For more information see [Template Syntax](../guide/template-syntax.html#event-binding).
tr(style=top)
@ -215,17 +220,17 @@ table(width="100%")
code-example(format="").
<div ng-controller="MovieListCtrl as vm">
:marked
In Angular 1, the `ng-controller` directive attaches a controller to the view.
In Angular 1, the `ng-controller` directive attaches a controller to the view.
Using the `ng-controller` (or defining the controller as part of the routing) ties the
view to the controller code associated with that view.
view to the controller code associated with that view.
td
:marked
### Component decorator
+makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'component')(format="." )
:marked
In Angular 2, the template no longer specifies its associated controller.
In Angular 2, the template no longer specifies its associated controller.
Rather, the component specifies its associated template as part of the component class decorator.
For more information see [Architecture Overview](../guide/architecture.html#component).
tr(style=top)
@ -262,9 +267,9 @@ table(width="100%")
:marked
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.
For more information on property binding see [Template Syntax](../guide/template-syntax.html#property-binding).
In Angular 2, `href` is no longer used for routing. Routing uses `routerLink` as shown in the third example.
+makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'router-link')(format="." )
:marked
@ -279,18 +284,18 @@ table(width="100%")
:marked
In Angular 1, the `ng-if` directive removes or recreates a portion of the DOM
based on an expression. If the expression is false, the element is removed from the DOM.
In this example, the `table` element is removed from the DOM unless the `movies` array has a length greater than zero.
td
:marked
### *ngIf
+makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.html', 'ngIf')(format="." )
:marked
The `*ngIf` directive in Angular 2 works the same as the `ng-if` directive in Angular 1,
The `*ngIf` directive in Angular 2 works the same as the `ng-if` directive in Angular 1,
it removes or recreates a portion of the DOM based on an expression.
In this example, the `table` element is removed from the DOM unless the `movies` array has a length.
The (*) before `ngIf` is required in this example.
For more information see [Structural Directives](../guide/structural-directives.html).
tr(style=top)
@ -309,9 +314,9 @@ table(width="100%")
+makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.html', 'ngModel')(format="." )
:marked
In Angular 2, **two-way binding** is denoted with [()], descriptively referred to as a "banana in a box".
This syntax is a short-cut for defining both property binding (from the component to the view)
This syntax is a short-cut for defining both property binding (from the component to the view)
and event binding (from the view to the component), thereby giving us two-way binding.
For more information on two-way binding with ngModel see [Template Syntax](../guide/template-syntax.html#ngModel).
tr(style=top)
td
@ -322,23 +327,23 @@ table(width="100%")
:marked
In Angular 1, the `ng-repeat` directive repeats the associated DOM element
for each item from the specified collection.
In this example, the table row (`tr`) element is repeated for each movie object in the collection of movies.
td
:marked
### *ngFor
+makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.html', 'ngFor')(format="." )
:marked
The `*ngFor` directive in Angular 2 is similar to the `ng-repeat` directive in Angular 1.
The `*ngFor` directive in Angular 2 is similar to the `ng-repeat` directive in Angular 1.
It repeats the associated DOM element for each item from the specified collection.
More accurately, it turns the defined element (`tr` in this example) and its contents into a template and
uses that template to instantiate a view for each item in the list.
Notice the other syntax differences:
The (*) before `ngFor` is required;
the `let` keyword identifies `movie` as an input variable;
the list preposition is `of`, not `in`.
For more information see [Structural Directives](../guide/structural-directives.html).
tr(style=top)
td
@ -351,7 +356,7 @@ table(width="100%")
:marked
In Angular 1, the `ng-show` directive shows or hides the associated DOM element based on
an expression.
In this example, the `div` element is shown if the `favoriteHero` variable is truthy.
td
:marked
@ -360,12 +365,12 @@ table(width="100%")
:marked
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.
To conditionally display an element, place the element's `hidden` property in square brackets and
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*.
In this example, the `div` element is hidden if the `favoriteHero` variable is not truthy.
For more information on property binding see [Template Syntax](../guide/template-syntax.html#property-binding).
tr(style=top)
td
@ -384,7 +389,7 @@ table(width="100%")
:marked
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.
For more information on property binding see [Template Syntax](../guide/template-syntax.html#property-binding).
tr(style=top)
td
@ -397,28 +402,28 @@ table(width="100%")
based on an expression. That expression is often a key-value control object with each
key of the object defined as a CSS style name, and each value defined as an expression
that evaluates to a value appropriate for the style.
In the example, the `color` style is set to the current value of the `colorPreference` variable.
td
:marked
### ngStyle
+makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'ngStyle')(format="." )
:marked
In Angular 2, the `ngStyle` directive works similarly. It sets a CSS style on an HTML element based on an expression.
In Angular 2, the `ngStyle` directive works similarly. It sets a CSS style on an HTML element based on an expression.
In the first example, the `color` style is set to the current value of the `colorPreference` variable.
Angular 2 also has **style binding**, which is good way to set a single style. This is shown in the second example.
For more information on style binding see [Template Syntax](../guide/template-syntax.html#style-binding).
For more information on the ngStyle directive see [Template Syntax](../guide/template-syntax.html#ngStyle).
tr(style=top)
td
:marked
### ng-switch
code-example(format="").
<div ng-switch="vm.favoriteHero &&
<div ng-switch="vm.favoriteHero &&
vm.checkMovieHero(vm.favoriteHero)">
<div ng-switch-when="true">
Excellent choice!
@ -433,7 +438,7 @@ table(width="100%")
:marked
In Angular 1, the `ng-switch` directive swaps the contents of
an element by selecting one of the templates based on the current value of an expression.
In this example, if `favoriteHero` is not set, the template displays "Please enter ...".
If the `favoriteHero` is set, it checks the movie hero by calling a controller method.
If that method returns `true`, the template displays "Excellent choice!".
@ -443,21 +448,21 @@ table(width="100%")
### ngSwitch
+makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.html', 'ngSwitch')(format="." )
:marked
In Angular 2, the `ngSwitch` directive works similarly.
In Angular 2, the `ngSwitch` directive works similarly.
It displays an element whose `*ngSwitchWhen` matches the current `ngSwitch` expression value.
In this example, if `favoriteHero` is not set, the `ngSwitch` value is `null`
and we see the `*ngSwitchDefault` paragraph, "Please enter ...".
If the `favoriteHero` is set, it checks the movie hero by calling a component method.
If that method returns `true`, we see "Excellent choice!".
If that methods returns `false`, we see "No movie, sorry!".
The (*) before `ngSwitchWhen` and `ngSwitchDefault` is required in this example.
For more information on the ngSwitch directive see [Template Syntax](../guide/template-syntax.html#ngSwitch).
:marked
[Back to top](#top)
a(id="filters-pipes")
.l-main-section
:marked
@ -468,7 +473,7 @@ a(id="filters-pipes")
table(width="100%")
col(width="50%")
col(width="50%")
col(width="50%")
tr
th Angular 1
th Angular 2
@ -513,9 +518,9 @@ table(width="100%")
:marked
### none
There is no comparable pipe in Angular 2 for performance reasons.
Filtering should be coded in the component.
Consider building a custom pipe if the same filtering code
will be reused in several templates.
Filtering should be coded in the component.
Consider building a custom pipe if the same filtering code
will be reused in several templates.
tr(style=top)
td
@ -546,7 +551,7 @@ table(width="100%")
+makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'slice')(format=".")
:marked
The `SlicePipe` does the same thing but the *order of the parameters is reversed* in keeping
with the JavaScript `Slice` method.
with the JavaScript `Slice` method.
The first parameter is the starting index; the second is the limit.
As in Angular 1, performance may improve if we code this operation within the component instead.
tr(style=top)
@ -577,9 +582,9 @@ table(width="100%")
+makeExample('cb-a1-a2-quick-reference/ts/app/app.component.html', 'number')(format=".")
:marked
The Angular 2 `number` pipe is similar.
It provides more functionality when defining
It provides more functionality when defining
the decimal places as shown in the second example above.
Angular 2 also has a `percent` pipe which formats a number as a local percentage
as shown in the third example.
tr(style=top)
@ -589,31 +594,31 @@ table(width="100%")
code-example.
<tr ng-repeat="movie in movieList | orderBy : 'title'">
:marked
Orders the collection as specified by the expression.
Orders the collection as specified by the expression.
In this example, the movieList is ordered by the movie title.
td
:marked
### none
There is no comparable pipe in Angular 2 for performance reasons.
Ordering/sorting the results should be coded in the component.
Consider building a custom pipe if the same ordering/sorting code
Ordering/sorting the results should be coded in the component.
Consider building a custom pipe if the same ordering/sorting code
will be reused in several templates.
:marked
[Back to top](#top)
a(id="controllers-components")
.l-main-section
:marked
## Controllers / Components
In Angular 1, we write the code that provides the model and the methods for the view in a **controller**.
In Angular 2, we build a **component**.
Because much of our Angular 1 code is in JavaScript, JavaScript code is shown in the Angular 1 column.
The Angular 2 code is shown using TypeScript.
table(width="100%")
col(width="50%")
col(width="50%")
col(width="50%")
tr
th Angular 1
th Angular 2
@ -627,13 +632,13 @@ table(width="100%")
}());
:marked
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.
This kept our controller code out of the global namespace.
td
:marked
### none
We don't need to worry about this in Angular 2 because we use ES 2015 modules
and modules handle the namespacing for us.
For more information on modules see [Architecture Overview](../guide/architecture.html#module).
tr(style=top)
td
@ -652,9 +657,9 @@ table(width="100%")
:marked
Angular 2 does not have its own module system. Instead we use ES 2015 modules.
ES 2015 modules are file based, so each code file is its own module.
We `import` what we need from the module files.
For more information on modules see [Architecture Overview](../guide/architecture.html#module).
tr(style=top)
td
@ -668,10 +673,10 @@ table(width="100%")
MovieListCtrl]);
:marked
In Angular 1, we have code in each controller that looks up an appropriate Angular module
and registers the controller with that module.
and registers the controller with that module.
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.
all dependencies injected into this controller, and a reference to the controller function.
td
:marked
### Component Decorator
@ -680,9 +685,9 @@ table(width="100%")
In Angular 2, we add a decorator to the component class to provide any required metadata.
The Component decorator declares that the class is a component and provides metadata about
that component, such as its selector (or tag) and its template.
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).
tr(style=top)
td
@ -692,17 +697,17 @@ table(width="100%")
function MovieListCtrl(movieService) {
}
:marked
In Angular 1, we write the code for the model and methods in a controller function.
In Angular 1, we write the code for the model and methods in a controller function.
td
:marked
### Component class
+makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'class')(format=".")
:marked
In Angular 2, we create a component class.
NOTE: If you are using TypeScript with Angular 1 then the only difference here is
that the component class must be exported using the `export` keyword.
For more information on components see [Architecture Overview](../guide/architecture.html#component).
tr(style=top)
td
@ -715,8 +720,8 @@ table(width="100%")
:marked
In Angular 1, we pass in any dependencies as controller function arguments.
In this example, we inject a `MovieService`.
We also guard against minification problems by telling Angular explicitly
We also guard against minification problems by telling Angular explicitly
that it should inject an instance of the `MovieService` in the first parameter.
td
:marked
@ -724,13 +729,13 @@ table(width="100%")
+makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'di')(format=".")
:marked
In Angular 2, we pass in dependencies as arguments to the component class constructor.
In this example, we inject a `MovieService`.
In this example, we inject a `MovieService`.
The first parameter's TypeScript type tells Angular what to inject even after minification.
For more information on dependency injection see [Architecture Overview](../guide/architecture.html#dependency-injection).
:marked
[Back to top](#top)
a(id="style-sheets")
.l-main-section
:marked
@ -743,7 +748,7 @@ a(id="style-sheets")
also encapculate a style sheet within a specific component.
table(width="100%")
col(width="50%")
col(width="50%")
col(width="50%")
tr
th Angular 1
th Angular 2
@ -755,7 +760,7 @@ table(width="100%")
<link href="styles.css" rel="stylesheet" />
:marked
In Angular 1, we use a `link` tag in the head section of our `index.html` file
to define the styles for our application.
to define the styles for our application.
td
:marked
### Link tag
@ -765,11 +770,11 @@ table(width="100%")
But we can now also encapsulate styles for our components.
:marked
### StyleUrls
In Angular 2, we can use the `styles` or `styleUrls` property of the `@Component` metadata to define
In Angular 2, we can use the `styles` or `styleUrls` property of the `@Component` metadata to define
a style sheet for a particular component.
+makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'style-url')(format=".")
:marked
This allows us to set appropriate styles for individual components that wont leak into
This allows us to set appropriate styles for individual components that wont leak into
other parts of the application.
:marked
[Back to top](#top)
@ -778,10 +783,10 @@ a(id="string-dates")
.l-main-section
:marked
## Appendix: String dates
Currently the Angular 2 `date` pipe does not process string dates such as
"2015-12-19T00:00:00".
As a work around, subclass the Angular `DatePipe` with a version that can convert strings
and substitute that pipe in the HTML:
@ -789,7 +794,7 @@ a(id="string-dates")
:marked
Then import and declare that pipe in the `@Component` metadata `pipes` array:
:marked
+makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'date-pipe')(format=".")
+makeExample('cb-a1-a2-quick-reference/ts/app/movie-list.component.ts', 'date-pipe')(format=".")
:marked
[Back to top](#top)

View File

@ -3,50 +3,82 @@ include ../_util-fns
:marked
## Write *Component-Relative* URLs to component templates and style files
## 为组件模板和样式表文件写*相对于组件的*URL
Our components often refer to external template and style files.
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='.')
:marked
By default, we *must* specify the full path back to the application root.
We call this an ***absolute path*** because it is *absolute* with respect to the application root.
默认情况下,我们*必须*指定一个到应用根目录的完整路径。
我们称之为***绝对路径***,因为如果以应用程序的根目录为基准来看,它就是*绝对路径*。
There are two problems with an *absolute path*:
使用*绝对路径*有两个问题:
1. We have to remember the full path back to the application root.
1. 我们不得不记住到应用程序根目录的完整路径。
1. We have to update the URL when we move the component around in the application files structure.
1. 当我们在应用的文件结构中移动这个组件时将不得不更新这个URL
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!*
*没问题!*
.alert.is-important
:marked
We can if we build our application as `commonjs` modules and load those modules
with a suitable package loader such as `systemjs` or `webpack`.
Learn why [below](#why-default).
如果我们把应用构建成`commonjs`模块,并用一个合适的包加载器(比如`systemjs`或`webpack`)加载那些模块,就可以了。
[在下方](#why-default)可以学到原理。
The Angular 2 CLI uses these technologies and defaults to the
*component-relative path* approach described here.
CLI users can skip this chapter or read on to understand
how it works.
Angular 2 CLI(命令行界面)使用这些技术,并默认采用这里所说的*组件相对路径*方法。
用CLI用户可以跳过本章并且往后阅读来了解它是怎么工作的。
.l-main-section
:marked
## _Component-Relative_ Paths
Our goal is to specify template and style URLs *relative* to their component class files,
## _组件相对_路径
Our goal is to specify template and style URLs *relative* to their component class files,
hence the term ***component-relative path***.
我们的目标是指定*相对*于组件类的模板和样式表的URL因此得名***组件相对路径***。
The key to success is following a convention that puts related component files in well-known locations.
成功的关键是遵循一个约定:把相对组件的文件放进众所周知的位置。
We recommend keeping component template and component-specific style files as *siblings* of their
companion component class files.
Here we see the three files for `SomeComponent` sitting next to each other in the `app` folder.
companion component class files.
Here we see the three files for `SomeComponent` sitting next to each other in the `app` folder.
我们建议把组件的模板和组件特有的样式表文件作为组件类文件的“兄弟”。
这里我们看到在`app`目录下依次有`SomeComponent`的三个文件。
.filetree
.file app
.children
@ -57,27 +89,45 @@ include ../_util-fns
:marked
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*
### 设置*moduleId*
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`属性就可以了,就像这样:
+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/`去掉了。结果是这样的:
+makeExample('cb-component-relative-paths/ts/app/some.component.ts','relative-config')(format='.')
.alert.is-helpful
:marked
Webpack users may prefer [an alternative approach](#webpack) that uses `require`.
Webpack用户可能更喜欢[一个替代方案](#webpack):使用`require`。
.l-main-section
:marked
## Source
## 源码
**We can see the [live example](/resources/live-examples/cb-component-relative-paths/ts/plnkr.html)**
and download the source code from there
or simply read the pertinent source here.
**我们可以参见[在线范例](/resources/live-examples/cb-component-relative-paths/ts/plnkr.html)**
并从中下载源码或只在这里阅读相关源码。
+makeTabs(
`cb-component-relative-paths/ts/app/some.component.ts,
cb-component-relative-paths/ts/app/some.component.html,
@ -90,51 +140,90 @@ a#why-default
.l-main-section
:marked
## Appendix: why *component-relative* is not the default
## 附录:为什么*组件相对路径*不是默认方式
A *component-relative* path is obviously superior to an *absolute* path.
Why did Angular default to the *absolute* path?
Why do *we* have to set the `moduleId`? Why can't Angular set it?
*组件相对路径*明显比*绝对路径*高级一点。
为什么Angular默认采用了*绝对路径*呢?
为什么*我们*不得不设置`moduleId`呢Angular为什么不能自己设置它
First, let's look at what happens if we use a relative path and omit the `moduleId`.
首先,如果只使用相对路径而省略掉`moduleId`,我们来看看会发生什么。
`EXCEPTION: Failed to load some.component.html`
`EXCEPTION: Failed to load some.component.html`
Angular can't find the file so it throws an error.
Why can't Angular calculate the template and style URLs from the component file's location?
Angular找不到这个文件所以它抛出一个错误。
Why can't Angular calculate the template and style URLs from the component file's location?
为什么Angular不能相对于组件类文件的路径来自动计算模板和样式表的URL呢
Because the location of the component can't be determined without the developer's help.
Angular apps can be loaded in many ways: from individual files, from SystemJS packages, or
from CommonJS packages, to name a few.
We might generate modules in any of several formats.
from CommonJS packages, to name a few.
We might generate modules in any of several formats.
We might not be writing modular code at all!
With this diversity of packaging and module load strategies,
因为如果没有开发人员的帮助,组件的位置是检测不到的。
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.
由于存在这么多打包和模块加载策略所以Angular不可能知道在运行期这些文件的正确位置。
The only location Angular can be sure of is the URL of the `index.html` home page, the application root.
So by default it resolves template and style paths relative to the URL of `index.html`.
That's why we previously wrote our file URLs with an `app/` base path prefix.
Angular能够确定的唯一的位置是首页`index.html`的URL也就是应用的根目录。
所以,默认情况下,它只能计算相对于`index.html`的模板和样式表路径。
这就是为什么我们以前用`app/`基准路径的前缀来写文件的URL。
But *if* we follow the recommended guidelines and we write modules in `commonjs` format
and we use a module loader that *plays nice*,
*then* we — the developers of the application —
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。
That knowledge enables us to tell Angular where the *component* file is
by setting the `moduleId`:
这种认知让我们得以通过设置`moduleId`来告诉Angular*组件类*文件在哪里:
+makeExample('cb-component-relative-paths/ts/app/some.component.ts','module-id')(format='.')
a#webpack
.l-main-section
:marked
## Webpack: load templates and styles with *require*
## Webpack: 使用*require*加载模板和样式表
Webpack developers have an alternative to `moduleId`.
Webpack开发者有`moduleId`的另一个备选方案。
They can load templates and styles at runtime by setting the component metadata `template` and `style` properties
with `require` statements that reference *component-relative* URLS.
通过把组件元数据中的`template`和`style`属性设置为`require`语句,并引用一个*相对于组件的*URL他们可以在运行期间加载模板和样式表。
+makeExample('webpack/ts/src/app/app.component.ts')(format='.')
:marked
See the [Introduction to Webpack](../guide/webpack.html).
参见[Webpack简介](../guide/webpack.html)。

View File

@ -71,7 +71,7 @@ a#hooks-overview
:marked
## Component lifecycle Hooks
##组件生命周期钩子
## 组件生命周期钩子
Directive and component instances have a lifecycle
as Angular creates, updates, and destroys them.