Rex的版本出现jade编译错误,恢复到Wang的版本
This commit is contained in:
parent
eeac0d8b00
commit
cb95a74253
|
@ -9,8 +9,7 @@ block includes
|
|||
:marked
|
||||
Our Angular application manages what the user sees and can do, achieving this through the interaction of a Component class instance (the *component*) and its user-facing template.
|
||||
|
||||
我们的Angular应用管理着用户之所见和之所能,并通过组件类的实例以及组件面向用户的模板来与用户交互。
|
||||
|
||||
我们的Angular应用管理着用户之所见和所为,并通过组件类的实例以及组件面向用户的模板来与用户交互。
|
||||
|
||||
Many of us are familiar with the component/template duality from our experience with model-view-controller (MVC) or model-view-viewmodel (MVVM). In Angular, the component plays the part of the controller/viewmodel, and the template represents the view.
|
||||
|
||||
|
@ -61,15 +60,15 @@ block includes
|
|||
* [模板表达式操作符](#expression-operators)
|
||||
* [pipe](#pipe)
|
||||
* [管道](#pipe)
|
||||
* ["safe navigation operator" (?.)](#safe-navigation-operator)
|
||||
* [safe navigation operator (?.)](#safe-navigation-operator)
|
||||
* [“安全导航操作符”(?.)](#safe-navigation-operator)
|
||||
|
||||
p.
|
||||
The #[+liveExampleLink2()]
|
||||
demonstrates all of the syntax and code snippets described in this chapter.
|
||||
p.
|
||||
这个#[+liveExampleLink2('在线例子')]演示了本章中描述的所有语法和代码片段。
|
||||
|
||||
The #[+liveExampleLink2()]
|
||||
演示了本章中描述的所有语法和代码片段。
|
||||
// #docregion html-1
|
||||
.l-main-section
|
||||
:marked
|
||||
## HTML
|
||||
|
@ -78,7 +77,6 @@ p.
|
|||
|
||||
HTML是Angular模板的“语言”。我们的[“快速起步”](../quickstart.html)应用就有一个模板是纯HTML的:
|
||||
|
||||
|
||||
code-example(language="html" escape="html").
|
||||
<h1>My First Angular 2 App</h1>
|
||||
|
||||
|
@ -106,7 +104,6 @@ code-example(language="html" escape="html").
|
|||
We met the double-curly braces of interpolation, `{{` and `}}`, early in our Angular education.
|
||||
|
||||
在以前的Angular教程中,我们遇到过由双花括号括起来的插值表达式,`{{`和`}}`。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'first-interpolation')(format=".")
|
||||
:marked
|
||||
We use interpolation to weave calculated strings into the text between HTML element tags and within attribute assignments.
|
||||
|
@ -126,13 +123,11 @@ code-example(language="html" escape="html").
|
|||
and then **converts to a string**. The following interpolation illustrates the point by adding the two numbers within braces:
|
||||
|
||||
更一般化的说法是:括号间的素材是一个**模板表达式**,Angular首先**对它求值**然后把它**转换成字符串**。下列插值表达式通过把括号中的两个数字相加说明了这一点:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'sum-1')(format=".")
|
||||
:marked
|
||||
The expression can invoke methods of the host component, as we do here with `getVal()`:
|
||||
|
||||
这个表达式可以调用所属组件的方法,就像下面用的`getVal()`:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'sum-2')(format=".")
|
||||
:marked
|
||||
Angular evaluates all expressions in double curly braces, converts the expression results to strings, and concatenates them with neighboring literal strings. Finally,
|
||||
|
@ -183,33 +178,28 @@ code-example(language="html" escape="html").
|
|||
JavaScript中那些具有或可能引发副作用的表达式是被禁止的,包括:
|
||||
|
||||
* assignments (`=`, `+=`, `-=`, ...)
|
||||
* 赋值 (`=`, `+=`, `-=`,...)
|
||||
* 赋值 (`=`, `+=`, `-=`, ...)
|
||||
* !{__new_op}
|
||||
* !{__new_op}`new`运算符
|
||||
* `new`运算符
|
||||
* chaining expressions with !{__chaining_op}
|
||||
* 使用{__chaining_op}的链式表达式
|
||||
* 使用`;`或`,`的链式表达式
|
||||
* increment and decrement operators (`++` and `--`)
|
||||
* 自增或自减操作符(`++`和`--`)
|
||||
|
||||
:marked
|
||||
Other notable differences from #{_JavaScript} syntax include:
|
||||
|
||||
和#{JavaScript}语法的其它显著不同包括:
|
||||
和JavaScript语法的其它显著不同包括:
|
||||
|
||||
block notable-differences
|
||||
:marked
|
||||
* no support for the bitwise operators `|` and `&`
|
||||
|
||||
* 不支持位运算 `|` 和 `&`
|
||||
|
||||
* new [template expression operators](#expression-operators), such as `|` and `?.`
|
||||
|
||||
* 具有新的 [模板表达式运算符](#expression-operators),比如`|`和`?.`
|
||||
|
||||
h3#expression-context Expression context
|
||||
|
||||
h3#expression-context 表达式上下文
|
||||
|
||||
block template-expressions-cannot
|
||||
:marked
|
||||
Perhaps more surprising, template expressions cannot refer to anything in
|
||||
|
@ -217,8 +207,8 @@ block template-expressions-cannot
|
|||
can’t call `console.log` or `Math.max`. They are restricted to referencing
|
||||
members of the expression context.
|
||||
|
||||
或许你感到惊讶,模板表达式不能引用任何全局命名空间。它们不能引用`window`或者`document`。
|
||||
它们不能调用`console.log`或者`Max.max`。它们只能引用表达式上下文中的成员。
|
||||
你可能会感到惊讶,模板表达式不能引用全局命名空间中的任何东西。它们不能引用<code>window</code>或<code>document</code>。
|
||||
它们不能调用<code>console.log</code>或<code>Math.max</code>。它们被局限于只能访问来自表达式上下文中的成员。
|
||||
|
||||
:marked
|
||||
The *expression context* is typically the **component instance**, which is
|
||||
|
@ -319,7 +309,6 @@ block template-expressions-cannot
|
|||
one of its dependent values changes.
|
||||
|
||||
用Angular的术语说,一个幂等的表达式应该总是返回*完全相同的东西*,直到它所依赖的值中有一个变了。
|
||||
|
||||
:marked
|
||||
Dependent values should not change during a single turn of the event loop.
|
||||
If an idempotent expression returns a string or a number, it returns the same string or number
|
||||
|
@ -360,7 +349,6 @@ block template-expressions-cannot
|
|||
|
||||
响应事件是Angular中“单向数据流”的另一面。
|
||||
在事件循环的这一回合中,我们可以随意改变任何地方的任何东西。
|
||||
|
||||
:marked
|
||||
Like template expressions, template *statements* use a language that looks like #{_JavaScript}.
|
||||
The template statement parser is different than the template expression parser and
|
||||
|
@ -368,15 +356,14 @@ block template-expressions-cannot
|
|||
(with !{__chaining_op}).
|
||||
|
||||
和模板表达式一样,模板*语句*也是一个一个看起来很像JavaScript的语言。
|
||||
模板语句解析器和模板表达式解析器有所不同,它的特别之处在于它既支持支持基本赋值(`=`)
|
||||
又支持(!{__chaining_op})。
|
||||
|
||||
模板语句解析器和模板表达式解析器有所不同,它的特别之处在于它既支持支持基本赋值(`=`)又支持使用分号(`;`)和逗号(`,`)把表达式串起来。
|
||||
|
||||
However, certain #{_JavaScript} syntax is not allowed:
|
||||
|
||||
但无论如何,某些#{JavaScript}语法仍然是不允许的:
|
||||
* !{__new_op}
|
||||
* `new`运算符!{__new_op}
|
||||
|
||||
但无论如何,某些JavaScript语法仍然是不允许的:
|
||||
* the `new` operator
|
||||
* `new`运算符
|
||||
* increment and decrement operators, `++` and `--`
|
||||
* 自增和自减运算符:`++`和`--`
|
||||
* operator assignment, such as `+=` and `-=`
|
||||
|
@ -393,7 +380,7 @@ block template-expressions-cannot
|
|||
As with expressions, statements can refer only to what's in the statement context — typically the
|
||||
**component instance** to which we're binding the event.
|
||||
|
||||
和表达式中一样,语句只能引用语句上下文中 —— 典型的就是我们正在绑定事件的那个**组件的实例**。
|
||||
和表达式中一样,语句只能引用语句上下文中 —— 典型的就是我们正在绑定事件的那个**组件的实例** —— 中的内容。
|
||||
|
||||
block statement-context
|
||||
:marked
|
||||
|
@ -401,9 +388,6 @@ block statement-context
|
|||
can’t refer to `window` or `document`. They can’t call `console.log` or
|
||||
`Math.max`.
|
||||
|
||||
模板声明不能引用任何全局命名空间的东西。它们不能引用`window`或`document`。
|
||||
它们不能调用`console.log`或`Math.max`。
|
||||
|
||||
:marked
|
||||
The *onSave* in `(click)="onSave()"` is sure to be a method of the data-bound component instance.
|
||||
|
||||
|
@ -481,22 +465,26 @@ table
|
|||
[target] = "expression"
|
||||
bind-target = "expression"
|
||||
td
|
||||
p Interpolation<br>
|
||||
p 插值表达式<br>
|
||||
p Property<br>
|
||||
p 属性<br>
|
||||
p Attribute<br>
|
||||
p Attribute<br>
|
||||
p Class<br>
|
||||
p 类<br>
|
||||
p Interpolation
|
||||
p 插值表达式
|
||||
p Property
|
||||
p 属性
|
||||
p Attribute
|
||||
p Attribute
|
||||
p Class
|
||||
p 类
|
||||
p Style
|
||||
p 样式
|
||||
tr
|
||||
td
|
||||
p One-way<br>from view target<br>to data source
|
||||
p 单向<br>从视图目标<br>到数据源
|
||||
p One-way
|
||||
p 单向
|
||||
p from view target
|
||||
p 从视图目标
|
||||
p to data source
|
||||
p 到数据源
|
||||
td
|
||||
code-example(format="" ).
|
||||
code-example().
|
||||
(target) = "statement"
|
||||
on-target = "statement"
|
||||
td
|
||||
|
@ -507,7 +495,7 @@ table
|
|||
p Two-way
|
||||
p 双向
|
||||
td
|
||||
code-example(format="" ).
|
||||
code-example().
|
||||
[(target)] = "expression"
|
||||
bindon-target = "expression"
|
||||
td
|
||||
|
@ -565,7 +553,6 @@ table
|
|||
and drop them into our templates as if they were native HTML elements.
|
||||
|
||||
然后,我们学着用包含HTML的组件创建新元素,如果把它扔进我们的模板,它就和原生的HTML元素一般无二。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'hero-detail-1')(format=".")
|
||||
:marked
|
||||
That’s HTML Plus.
|
||||
|
@ -576,7 +563,6 @@ table
|
|||
|
||||
现在我们开始学习数据绑定。我们碰到的第一种数据绑定看起来是这样的:
|
||||
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'disabled-button-1')(format=".")
|
||||
:marked
|
||||
We’ll get to that peculiar bracket notation in a moment. Looking beyond it,
|
||||
|
@ -594,7 +580,6 @@ table
|
|||
实际上,一旦我们开始数据绑定,我们就不再跟Attribute打交道了。我们并不是在设置Attribute,
|
||||
而是在设置DOM元素、组件和指令的Property。
|
||||
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
### HTML attribute vs. DOM property
|
||||
|
@ -674,7 +659,6 @@ table
|
|||
|
||||
**就算名字相同,HTML Attribute和DOM Property也不是同一样东西。**
|
||||
|
||||
|
||||
:marked
|
||||
This is so important, we’ll say it again.
|
||||
|
||||
|
@ -694,7 +678,6 @@ table
|
|||
|
||||
在Angular 2的世界中,Attribute唯一的作用是用来初始化元素和指令的状态。
|
||||
当进行数据绑定时,我们只是在与元素和指令的Property和事件打交道,而Attribute就完全靠边站了。
|
||||
|
||||
:marked
|
||||
With this model firmly in mind, let's learn about binding targets.
|
||||
|
||||
|
@ -806,26 +789,22 @@ table
|
|||
|
||||
这种最常用的属性绑定会把元素的属性设置为组件中属性的值。
|
||||
下面这个例子中,会把image元素的`src`属性绑定到组件的`heroImageUrl`属性上:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'property-binding-1')(format=".")
|
||||
:marked
|
||||
Another example is disabling a button when the component says that it `isUnchanged`:
|
||||
|
||||
另一个例子是当组件说它`isUnchanged`(未改变)时禁用一个按钮:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'property-binding-2')(format=".")
|
||||
:marked
|
||||
Another is setting a property of a directive:
|
||||
|
||||
另一个例子是设置指令的属性:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'property-binding-3')(format=".")
|
||||
:marked
|
||||
Yet another is setting the model property of a custom component (a great way
|
||||
for parent and child components to communicate):
|
||||
|
||||
还有另一个例子是设置一个自定义组件的模型属性(这是父子组件之间通讯的重要途径):
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'property-binding-4')(format=".")
|
||||
:marked
|
||||
### One-way *in*
|
||||
|
@ -860,7 +839,6 @@ table
|
|||
参见API参考中的[viewChild](../api/core/ViewChild-var.html)和
|
||||
[contentChild](../api/core/ContentChild-var.html)。
|
||||
|
||||
|
||||
// TODO (global): once we have api docs everywhere, change /docs/ts/latest/ to ../
|
||||
|
||||
:marked
|
||||
|
@ -875,7 +853,6 @@ table
|
|||
Some people prefer the `bind-` prefix alternative, known as the *canonical form*:
|
||||
|
||||
有些人喜欢用`bind-`前缀的可选形式,并称之为*规范形式*:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'property-binding-5')(format=".")
|
||||
:marked
|
||||
The target name is always the name of a property, even when it appears to be the name of something else. We see `src` and may think it’s the name of an attribute. No. It’s the name of an image element property.
|
||||
|
@ -887,7 +864,6 @@ table
|
|||
as it is in the following example:
|
||||
|
||||
元素属性可能是最常见的绑定目标,但Angular会先去看这个名字是否是某个已知指令的属性名,就像下面的例子中一样:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'property-binding-3')(format=".")
|
||||
|
||||
.l-sub-section
|
||||
|
@ -935,7 +911,6 @@ table
|
|||
The `hero` property of the `HeroDetail` component expects a `Hero` object, which is exactly what we’re sending in the property binding:
|
||||
|
||||
`HeroDetail`组件的`hero`属性想要一个`Hero`对象,那我们就要在属性绑定中精确的给它一个`Hero`对象:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'property-binding-4')(format=".")
|
||||
|
||||
block dart-type-exceptions
|
||||
|
@ -955,7 +930,6 @@ block dart-type-exceptions
|
|||
Don't make the following mistake:
|
||||
|
||||
不要出现这样的失误:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'property-binding-6')(format=".")
|
||||
|
||||
block dart-type-exception-example
|
||||
|
@ -982,7 +956,7 @@ a(id="one-time-initialization")
|
|||
|
||||
我们像在标准HTML中一样用这种方式初始化Attribute,它在初始化指令和组件的属性时也同样工作得很好。
|
||||
下面这个例子把`HeroDetailComponent`的`prefix`属性初始化成了一个固定的字符串,而不是模板表达式。Angular设置它,然后忘记它。
|
||||
|
||||
// #enddocregion property-binding-12
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'property-binding-7')(format=".")
|
||||
:marked
|
||||
The `[hero]` binding, on the other hand, remains a live binding to the component's `currentHero` property.
|
||||
|
@ -994,7 +968,6 @@ a(id="one-time-initialization")
|
|||
We often have a choice between interpolation and property binding. The following binding pairs do the same thing:
|
||||
|
||||
我们通常得在插值表达式和属性绑定之间做出选择。下列这几对绑定做的事情完全相同:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'property-binding-vs-interpolation')(format=".")
|
||||
:marked
|
||||
Interpolation is a convenient alternative for property binding in many cases.
|
||||
|
@ -1012,7 +985,6 @@ a(id="one-time-initialization")
|
|||
我们倾向于可读性,所以倾向于插值表达式。
|
||||
我们建议建立组织级的代码风格规定,然后选择一种形式,既能遵循规则,又能让手头儿的任务做起来更自然。
|
||||
|
||||
|
||||
.l-main-section
|
||||
:marked
|
||||
<a id="other-bindings"></a>
|
||||
|
@ -1027,7 +999,6 @@ a(id="one-time-initialization")
|
|||
We can set the value of an attribute directly with an **attribute binding**.
|
||||
|
||||
我们可以通过**Attribute绑定**来直接设置Attribute的值。
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
This is the only exception to the rule that a binding sets a target property. This is the only binding that creates and sets an attribute.
|
||||
|
@ -1092,7 +1063,6 @@ code-example(format="nocode").
|
|||
Here we bind `[attr.colspan]` to a calculated value:
|
||||
|
||||
这里我们把`[attr.colspan]`绑定成一个通过计算得到的值:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'attrib-binding-colspan')(format=".")
|
||||
:marked
|
||||
Here's how the table renders:
|
||||
|
@ -1108,7 +1078,6 @@ code-example(format="nocode").
|
|||
is to set ARIA attributes, as in this example:
|
||||
|
||||
Attribute绑定的主要用例之一是设置ARIA Attribute(译注:ARIA指可访问性,用于给残障人士访问互联网提供便利),就像这个例子中一样:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'attrib-binding-aria')(format=".")
|
||||
:marked
|
||||
### Class binding
|
||||
|
@ -1130,13 +1099,11 @@ code-example(format="nocode").
|
|||
with class bindings. Here's how we set the attribute without binding:
|
||||
|
||||
下列例子示范了如何通过类绑定来添加和移除应用的"special"类。不用绑定直接设置Attribute时是这样的:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'class-binding-1')(format=".")
|
||||
:marked
|
||||
We can replace that with a binding to a string of the desired class names; this is an all-or-nothing, replacement binding.
|
||||
|
||||
我们可以把它改写为一个绑定到所需类名的绑定;这是一个或者全有或者全无的替换型绑定(译注:即当badCurly有值时class这个Attribute设置的内容会被完全覆盖)。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'class-binding-2')(format=".")
|
||||
|
||||
block dart-class-binding-bug
|
||||
|
@ -1148,9 +1115,7 @@ block dart-class-binding-bug
|
|||
It removes the class when the expression is #{_falsey}.
|
||||
|
||||
最后,我们可以绑定到一个特定的类名。
|
||||
当模板表达式的求值结果是真值#{_truthy}时,Angular会添加这个类,反之,当表达式为#{_falsey}则移除它。
|
||||
|
||||
|
||||
当模板表达式的求值结果是真值时,Angular会添加这个类,反之则移除它。
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'class-binding-3')(format=".")
|
||||
|
||||
.l-sub-section
|
||||
|
@ -1180,7 +1145,6 @@ block dart-class-binding-bug
|
|||
Some style binding styles have unit extension. Here we conditionally set the font size in “em” and “%” units .
|
||||
|
||||
有些样式绑定中的样式带有单位。在这里,我们可以根据条件用“em”和“%”来设置字体大小的单位。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'style-binding-2')(format=".")
|
||||
|
||||
.l-sub-section
|
||||
|
@ -1190,7 +1154,6 @@ block dart-class-binding-bug
|
|||
|
||||
虽然这是一个设置单一样式的好办法,但我们通常更喜欢使用[NgStyle指令](#ngStyle)来同时设置多个内联样式。
|
||||
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
Note that a _style property_ name can be written in either
|
||||
|
@ -1229,7 +1192,6 @@ block style-property-name-dart-diff
|
|||
|
||||
事件绑定语法由等号左侧带圆括号的**目标事件**,和右侧一个引号中的[模板语句](#template-statements)组成。
|
||||
下列事件绑定监听按钮的点击事件。无论什么时候,发生点击时,都会调用组件的`onSave()`方法。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'event-binding-1')(format=".")
|
||||
:marked
|
||||
### Target event
|
||||
|
@ -1238,20 +1200,17 @@ block style-property-name-dart-diff
|
|||
identifies the target event. In the following example, the target is the button’s click event.
|
||||
|
||||
**圆括号中的名称** —— 比如`(click)` —— 标记出了目标事件。在下面这个例子中,目标是按钮的click事件。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'event-binding-1')(format=".")
|
||||
:marked
|
||||
Some people prefer the `on-` prefix alternative, known as the *canonical form*:
|
||||
|
||||
有些人更喜欢带`on-`前缀的可选形式,称之为*规范形式*:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'event-binding-2')(format=".")
|
||||
:marked
|
||||
Element events may be the more common targets, but Angular looks first to see if the name matches an event property
|
||||
of a known directive, as it does in the following example:
|
||||
|
||||
元素事件可能是更常见的目标,但Angular会先看这个名字是否能匹配上已知指令的事件属性,就像下面这个例子:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'event-binding-3')(format=".")
|
||||
|
||||
.l-sub-section
|
||||
|
@ -1267,7 +1226,6 @@ block style-property-name-dart-diff
|
|||
|
||||
### *$event* and event handling statements
|
||||
### *$event*和事件处理语句
|
||||
|
||||
In an event binding, Angular sets up an event handler for the target event.
|
||||
|
||||
在事件绑定中,Angular会为目标事件设置事件处理器。
|
||||
|
@ -1296,7 +1254,6 @@ block style-property-name-dart-diff
|
|||
Consider this example:
|
||||
|
||||
考虑这个范例:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'without-NgModel')(format=".")
|
||||
:marked
|
||||
We’re binding the input box `value` to a `firstName` property, and we’re listening for changes by binding to the input box’s `input` event.
|
||||
|
@ -1340,7 +1297,6 @@ block style-property-name-dart-diff
|
|||
Here are the pertinent excerpts from that `HeroDetailComponent`:
|
||||
|
||||
这里是来自`HeroDetailComponent`的相关摘要:
|
||||
|
||||
+makeExample('template-syntax/ts/app/hero-detail.component.ts',
|
||||
'template-1', 'HeroDetailComponent.ts (template)')(format=".")
|
||||
+makeExample('template-syntax/ts/app/hero-detail.component.ts',
|
||||
|
@ -1368,7 +1324,6 @@ block style-property-name-dart-diff
|
|||
|
||||
### Template statements have side effects
|
||||
### 模板语句有副作用
|
||||
|
||||
The `deleteHero` method has a side effect: it deletes a hero.
|
||||
Template statement side effects are not just OK, they are expected.
|
||||
|
||||
|
@ -1383,6 +1338,7 @@ block style-property-name-dart-diff
|
|||
删除这个英雄会更新模型,还可能触发其它修改,包括向远端服务器的查询和保存。
|
||||
这些变更通过系统进行扩散,并最终显示到当前以及其它视图中。
|
||||
这都是好事。
|
||||
|
||||
//
|
||||
:marked
|
||||
### Event bubbling and propagation [TODO: reinstate this section when it becomes true]
|
||||
|
@ -1422,10 +1378,10 @@ block style-property-name-dart-diff
|
|||
The `[(ngModel)]` two-way data binding syntax makes that easy. Here's an example:
|
||||
|
||||
`[(NgModel)]`双向数据绑定语法让它变得简单,这里是例子:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgModel-1')(format=".")
|
||||
.callout.is-important
|
||||
header [()] = banana in a box
|
||||
header [()] = 盒子里的香蕉
|
||||
:marked
|
||||
To remember that the parentheses go inside the brackets, visualize a *banana in a box*.
|
||||
|
||||
|
@ -1435,7 +1391,6 @@ block style-property-name-dart-diff
|
|||
Alternatively, we can use the canonical prefix form:
|
||||
|
||||
另外,我们也可以使用规范前缀形式:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgModel-2')(format=".")
|
||||
:marked
|
||||
There’s a story behind this construction, a story that builds on the property and event binding techniques we learned previously.
|
||||
|
@ -1448,7 +1403,6 @@ block style-property-name-dart-diff
|
|||
the `<input>` element's `value` property and `input` event.
|
||||
|
||||
通过分别绑定到`<input>`元素的`value`属性和`input`事件,我们能达到同样的效果。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'without-NgModel')(format=".")
|
||||
:marked
|
||||
That’s cumbersome. Who can remember which element property to set and what event reports user changes?
|
||||
|
@ -1462,7 +1416,6 @@ block style-property-name-dart-diff
|
|||
That `ngModel` directive hides these onerous details behind its own `ngModel` input and `ngModelChange` output properties.
|
||||
|
||||
`ngModel`指令通过它自己的`ngModel`输入属性和`ngModelChange`输出属性隐藏了这些繁琐的细节。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgModel-3')(format=".")
|
||||
.l-sub-section
|
||||
:marked
|
||||
|
@ -1485,7 +1438,6 @@ block style-property-name-dart-diff
|
|||
with a single declaration — which it can with the `[( )]` syntax:
|
||||
|
||||
我们不该两次引用这个数据属性。Angular应该能捕获组件的数据属性,并且把它设置为一个简单的定义 —— 那就用`[( )]`语法吧:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgModel-1')(format=".")
|
||||
|
||||
.l-sub-section
|
||||
|
@ -1498,10 +1450,7 @@ block style-property-name-dart-diff
|
|||
`[(ngModel)]`是一个更通用的模式中的具体例子,在这里,Angular会把`[(x)]`语法去掉语法糖,变成了一个供属性绑定用的输入属性`x`,和一个供事件绑定用的输出属性`xChange`。
|
||||
Angular通过在模板表达式的原始字符串后面追加上`=$event`,来构建出供事件绑定用的模板语句。
|
||||
|
||||
code-example(format="." ).
|
||||
[(x)]="hero.name" <==> [x]="hero.name" (xChange)="hero.name=$event"
|
||||
|
||||
> <span style="font-family:courier">[(_x_)]="_e_" <==> [_x_]="_e_" (<i>x</i>Change)="_e_=$event"</span>
|
||||
<span style="font-family:courier">[(_x_)]="_e_" <==> [_x_]="_e_" (<i>x</i>Change)="_e_=$event"</span>
|
||||
|
||||
We can write a two-way binding directive of our own to exploit this behavior.
|
||||
|
||||
|
@ -1521,7 +1470,6 @@ block style-property-name-dart-diff
|
|||
Let's try something silly like forcing the input value to uppercase:
|
||||
|
||||
来做点淘气的事儿吧,比如强制让输入值变成大写形式:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgModel-4')(format=".")
|
||||
:marked
|
||||
Here are all variations in action, including the uppercase version:
|
||||
|
@ -1550,7 +1498,6 @@ figure.image-display
|
|||
在Angular 2中我们不需要那么多指令。
|
||||
使用更强大、更富有表现力的Angular 2绑定系统,我们其实可以达到同样的效果。
|
||||
如果我们能用一个这样的简单绑定达到目的,为什么还需要创建一个指令来处理点击事件?
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'event-binding-1')(format=".")
|
||||
:marked
|
||||
We still benefit from directives that simplify complex tasks.
|
||||
|
@ -1589,21 +1536,18 @@ figure.image-display
|
|||
|
||||
A good way to apply `NgClass` is by binding it to a key:value control !{__objectAsMap}. Each key of the object is a CSS class name; its value is `true` if the class should be added, `false` if it should be removed.
|
||||
|
||||
绑定到一个 key:value!形式的控制对象{__objectAsMap},是应用`NgClass`的好方式。这个对象中的每个key都是一个CSS类名,如果它的value是`true`,这个类就会被加上,否则就会被移除。
|
||||
|
||||
绑定到一个 key:value 形式的控制对象,是应用`NgClass`的好方式。这个对象中的每个key都是一个CSS类名,如果它的value是`true`,这个类就会被加上,否则就会被移除。
|
||||
|
||||
:marked
|
||||
Consider a component method such as `setClasses` that manages the state of three CSS classes:
|
||||
|
||||
考虑一个像`setClasses`这样的组件方法,用于管理三个CSS类的状态。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.ts', 'setClasses')(format=".")
|
||||
:marked
|
||||
Now we can add an `NgClass` property binding that calls `setClasses`
|
||||
and sets the element's classes accordingly:
|
||||
|
||||
现在,我们可以添加一个`NgClass`属性绑定,它会调用`setClasses`,并据此设置元素的类:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgClass-1')(format=".")
|
||||
|
||||
<a id="ngStyle"></a>
|
||||
|
@ -1619,7 +1563,6 @@ figure.image-display
|
|||
A [style binding](#style-binding) is an easy way to set a *single* style value.
|
||||
|
||||
[样式绑定](#style-binding)是设置*单一*样式值的简单方式。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgStyle-1')(format=".")
|
||||
:marked
|
||||
The `NgStyle` directive may be the better choice
|
||||
|
@ -1636,14 +1579,12 @@ figure.image-display
|
|||
Consider a component method such as `setStyles` that returns an object defining three styles:
|
||||
|
||||
考虑一个类似于`setStyles`的组件方法,它返回一个定义三种样式的对象:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.ts', 'setStyles')(format=".")
|
||||
:marked
|
||||
Now we just add an `NgStyle` property binding that calls `setStyles`
|
||||
and sets the element's styles accordingly:
|
||||
|
||||
现在我们添加一个`NgStyle`属性绑定,让它调用`setStyles`,并据此设置元素的样式:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgStyle-2')(format=".")
|
||||
|
||||
<a id="ngIf"></a>
|
||||
|
@ -1651,10 +1592,9 @@ figure.image-display
|
|||
:marked
|
||||
### NgIf
|
||||
### NgIf
|
||||
|
||||
We can add an element subtree (an element and its children) to the DOM by binding an `NgIf` directive to a #{_truthy} expression.
|
||||
通过把`NgIf`指令绑定到一个真值#{_truthy}表达式,我们可以把一个元素的子树(元素及其子元素)添加到DOM上。
|
||||
|
||||
通过把`NgIf`指令绑定到一个真值表达式,我们可以把一个元素的子树(元素及其子元素)添加到DOM上。
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgIf-1')(format=".")
|
||||
|
||||
.alert.is-critical
|
||||
|
@ -1664,12 +1604,10 @@ figure.image-display
|
|||
|
||||
不要忘记了`ngIf`前面的星号(`*`)。
|
||||
要了解更多,参见[\*与<template>](#star-template)。
|
||||
|
||||
:marked
|
||||
Binding to a #{_falsey} expression removes the element subtree from the DOM.
|
||||
|
||||
绑定到一个假值#{_falsey}表达式将从DOM中移除元素的子树。
|
||||
|
||||
绑定到一个假值表达式将从DOM中移除元素的子树。
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgIf-2')(format=".")
|
||||
|
||||
block dart-no-truthy-falsey
|
||||
|
@ -1682,7 +1620,6 @@ block dart-no-truthy-falsey
|
|||
[class](#class-binding) or [style](#style-binding) binding:
|
||||
|
||||
我们可以通过[类绑定](#class-binding)或[样式绑定](#style-binding)来显示和隐藏一个元素的子树(元素及其子元素)。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgIf-3')(format=".")
|
||||
:marked
|
||||
Hiding a subtree is quite different from excluding a subtree with `NgIf`.
|
||||
|
@ -1802,13 +1739,11 @@ block dart-no-truthy-falsey
|
|||
Here is an example of `NgFor` applied to a simple `<div>`:
|
||||
|
||||
这里是一个例子,它把`NgFor`应用在一个简单的`<div>`上:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgFor-1')(format=".")
|
||||
:marked
|
||||
We can also apply an `NgFor` to a component element, as in this example:
|
||||
|
||||
我们也可以把`NgFor`应用在一个组件元素上,就像这个例子中一样:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgFor-2')(format=".")
|
||||
|
||||
.alert.is-critical
|
||||
|
@ -1823,7 +1758,6 @@ block dart-no-truthy-falsey
|
|||
|
||||
赋值给`*ngFor`的文本是一个用于指导重复器如何工作的“操作指南”。
|
||||
|
||||
|
||||
<a id="ngForMicrosyntax"></a>
|
||||
:marked
|
||||
#### NgFor microsyntax
|
||||
|
@ -1834,26 +1768,25 @@ block dart-no-truthy-falsey
|
|||
赋值给`*ngFor`的字符串并不是一个[模板表达式](#template-expressions)。
|
||||
它是一个*微语法* —— 由Angular自己解释的小型语言。在这个例子中,字符串`"let hero of heroes"`的含义是:
|
||||
|
||||
>*Take each hero in the `heroes` array, store it in the local `hero` variable, and make it available to the templated HTML
|
||||
for each iteration.*
|
||||
|
||||
> *Take each hero in the `heroes` #{_array}, store it in the local `hero` variable, and make it available to the templated HTML for each iteration.*
|
||||
|
||||
> *取出`heroes`数组中的每个英雄,把它存在一个局部变量`hero`中,并且在每个迭代中让它对模板HTML可用*
|
||||
>*取出`heroes`数组中的每个英雄,把它存在一个局部变量`hero`中,并且在每个迭代中让它对模板HTML可用*
|
||||
|
||||
Angular translates this instruction into a new set of elements and bindings.
|
||||
|
||||
Angular把这份“操作指南”翻译成一组“元素和绑定”。
|
||||
|
||||
:marked
|
||||
In the two previous examples, the `ngFor` directive iterates over the `heroes` #{_array} returned by the parent component’s `heroes` property,
|
||||
stamping out instances of the element to which it is applied.
|
||||
Angular creates a fresh instance of the template for each hero in the array.
|
||||
|
||||
在前面的两个例子中,`ngFor`指令在`heroes`#{_array}变量上进行迭代(它是由父组件的`heroes`属性返回的),以其所在的元素为模板“冲压”出很多实例。
|
||||
在前面的两个例子中,`ngFor`指令在`heroes`变量上进行迭代(它是由父组件的`heroes`属性返回的),以其所在的元素为模板“冲压”出很多实例。
|
||||
Angular为数组中的每个英雄创建了此模板的一个全新实例。
|
||||
|
||||
The `let` keyword before `hero` creates a template input variable called `hero`.
|
||||
|
||||
"hero"前面的`let`关键字创建了一个名叫`hero`的模板输入变量。
|
||||
|
||||
`hero`前面的`let`关键字创建了一个名叫`hero`的模板输入变量。
|
||||
|
||||
.alert.is-critical
|
||||
:marked
|
||||
|
@ -1882,7 +1815,6 @@ block dart-no-truthy-falsey
|
|||
The next example captures the index in a variable named `i`, using it to stamp out rows like "1 - Hercules Son of Zeus".
|
||||
|
||||
下一个例子把index捕获到了一个名叫`i`的变量中,使用它“冲压出”像"1 - Hercules Son of Zeus"这样的条目。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgFor-3')(format=".")
|
||||
.l-sub-section
|
||||
:marked
|
||||
|
@ -1890,7 +1822,6 @@ block dart-no-truthy-falsey
|
|||
|
||||
要学习更多的*类似index*的值,例如`last`、`even`和`odd`,请参阅[NgFor API 参考](../api/common/NgFor-directive.html)。
|
||||
|
||||
|
||||
:marked
|
||||
#### NgForTrackBy
|
||||
The `ngFor` directive has the potential to perform poorly, especially with large lists.
|
||||
|
@ -1918,7 +1849,6 @@ block dart-no-truthy-falsey
|
|||
|
||||
如果我们给它一个*追踪*函数,Angular就可以避免这种折腾。追踪函数告诉Angular:我们知道两个具有相同`hero.id`的对象其实是同一个英雄。
|
||||
下面就是这样一个函数:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.ts', 'trackByHeroes')(format=".")
|
||||
:marked
|
||||
Now set the `NgForTrackBy` directive to that *tracking* function.
|
||||
|
@ -1926,7 +1856,6 @@ block dart-no-truthy-falsey
|
|||
|
||||
现在,把`NgForTrackBy`指令设置为那个*追踪*函数。
|
||||
Angular从语法上提供了等价的可选变体,比如这两个:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgForTrackBy-2')(format=".")
|
||||
:marked
|
||||
The *tracking* function doesn't eliminate all DOM changes.
|
||||
|
@ -1972,14 +1901,12 @@ figure.image-display
|
|||
|
||||
在这一节,我们将掀开引擎盖儿,看看Angular是怎样替我们扒掉这个`*`,并且把这段HTML展开到`<template>`标签中的。
|
||||
|
||||
|
||||
:marked
|
||||
### Expanding `*ngIf`
|
||||
### 展开`*ngIf`
|
||||
We can do what Angular does ourselves and expand the `*` prefix syntax to template syntax. Here's some code with `*ngIf`:
|
||||
|
||||
我们可以像Angular一样,自己把`*`前缀语法展开成template语法,这里是`*ngIf`的一些代码:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'Template-1')(format=".")
|
||||
:marked
|
||||
The `currentHero` is referenced twice, first as the true/false condition for `NgIf` and
|
||||
|
@ -1991,13 +1918,11 @@ figure.image-display
|
|||
into an expression assigned to a `template` directive.
|
||||
|
||||
展开的第一步是把`ngIf`(没有`*`前缀)和它的内容传给一个表达式,再赋值给`template`指令。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'Template-2a')(format=".")
|
||||
:marked
|
||||
The next (and final) step unfolds the HTML into a `<template>` tag and `[ngIf]` [property binding](#property-binding):
|
||||
|
||||
下一步,也就是最后一步,是把HTML包裹进`<template>`标签和一个`[ngIf]`[属性绑定](#property-binding)中:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'Template-2')(format=".")
|
||||
:marked
|
||||
Notice that the `[hero]="currentHero"` binding remains on the child `<hero-detail>`
|
||||
|
@ -2005,12 +1930,10 @@ figure.image-display
|
|||
|
||||
注意,`[hero]="currengHero"`绑定留在了模板中的子元素`<hero-detail>`上。
|
||||
|
||||
block Remember the brackets!
|
||||
block 别忘了括号!
|
||||
block remember-the-brackets
|
||||
.callout.is-critical
|
||||
header Remember the brackets!
|
||||
header 别忘了括号!
|
||||
|
||||
:marked
|
||||
Don’t make the mistake of writing `ngIf="currentHero"`!
|
||||
That syntax assigns the *string* value "currentHero" to `ngIf`.
|
||||
|
@ -2030,7 +1953,6 @@ block 别忘了括号!
|
|||
|
||||
类似的转换也作用于`*ngSwitch`上。我们可以自己解开这个语法糖。
|
||||
这里是一个例子,首先是`*ngSwitchWhen`和`*ngSwitchDefault`,然后再解出`<template>`标签:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgSwitch-expanded')(format=".")
|
||||
:marked
|
||||
The `*ngSwitchWhen` and `*ngSwitchDefault` expand in exactly the same manner as `*ngIf`,
|
||||
|
@ -2060,19 +1982,16 @@ figure.image-display
|
|||
The `*ngFor` undergoes a similar transformation. We begin with an `*ngFor` example:
|
||||
|
||||
`*ngFor`要经历类似的转换。我们从一个`*ngFor`的例子开始:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'Template-3a')(format=".")
|
||||
:marked
|
||||
Here's the same example after transporting the `ngFor` to the `template` directive:
|
||||
|
||||
这里是在把`ngFor`传进`template`指令后的同一个例子:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'Template-3')(format=".")
|
||||
:marked
|
||||
And here it is expanded further into a `<template>` tag wrapping the original `<hero-detail>` element:
|
||||
|
||||
这里,它被进一步扩展成了包裹着原始`<hero-detail>`元素的`<template>`标签:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'Template-4')(format=".")
|
||||
:marked
|
||||
The `NgFor` code is a bit more complex than `NgIf` because a repeater has more moving parts to configure.
|
||||
|
@ -2083,7 +2002,6 @@ figure.image-display
|
|||
这种情况下,我们不得不记着创建并对用于标记列表的`NgForOf`指令和`NgForTrackBy`指令赋值。
|
||||
使用`*ngFor`语法比直接写这些展开后的HTML本身要简单多了。
|
||||
|
||||
|
||||
<a id="ref-vars"></a>
|
||||
.l-main-section
|
||||
:marked
|
||||
|
@ -2095,6 +2013,7 @@ figure.image-display
|
|||
**模板引用变量**是模板中对DOM元素或指令的引用。
|
||||
|
||||
It can be used with native DOM elements but also with Angular 2 components — in fact, it will work with any custom web component.
|
||||
|
||||
它能被用作原生DOM元素,但也能用于Angular 2组件 —— 实际上,它可以和任何自定义Web组件协同工作。
|
||||
|
||||
:marked
|
||||
|
@ -2109,7 +2028,6 @@ figure.image-display
|
|||
Here are two other examples of creating and consuming a Template reference variable:
|
||||
|
||||
这里是关于创建和消费模板引用变量的另外两个例子:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'ref-phone')(format=".")
|
||||
:marked
|
||||
The hash (`#`) prefix to "phone" means that we're defining a `phone` variable.
|
||||
|
@ -2136,7 +2054,6 @@ figure.image-display
|
|||
我们在这个`input`元素上定义了这些变量。
|
||||
我们把那些`input`元素对象传给button元素,在这里,它们被当做参数传给了事件绑定中的`call`方法。
|
||||
|
||||
|
||||
:marked
|
||||
### NgForm and template reference variables
|
||||
### NgForm和模板引用变量
|
||||
|
@ -2149,14 +2066,12 @@ figure.image-display
|
|||
|
||||
正如我们在[表单](forms.html)一章中所见过的,此表单的HTML可以做得相当复杂。
|
||||
下面是一个*简化过的*范例 —— 虽然仍算不上多简单。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'ref-form')(format=".")
|
||||
:marked
|
||||
A template reference variable, `theForm`, appears three times in this example, separated
|
||||
by a large amount of HTML.
|
||||
|
||||
模板引用变量`theForm`在这个例子中出现了三次,中间隔着一大段儿HTML。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'ref-form-a')(format=".")
|
||||
:marked
|
||||
What is the value of `theForm`?
|
||||
|
@ -2177,7 +2092,6 @@ figure.image-display
|
|||
|
||||
这解释了我们该如何通过检查`theForm.form.valid`来禁用提交按钮,以及如何把一个信息量略大的对象传给父组件的`onSubmit`方法。
|
||||
|
||||
|
||||
<a id="inputs-outputs"></a>
|
||||
.l-main-section
|
||||
:marked
|
||||
|
@ -2219,7 +2133,6 @@ figure.image-display
|
|||
|
||||
绑定的*目标*是绑定符:`[]`、`()`或`[()]`中的属性或事件名,*源*则是引号(`" "`)中的部分或插值符号(`{{}}`)中的部分。
|
||||
|
||||
|
||||
Every member of a **source** directive is automatically available for binding.
|
||||
We don't have to do anything special to access a directive member in a template expression or statement.
|
||||
|
||||
|
@ -2236,7 +2149,6 @@ figure.image-display
|
|||
that are referenced within quoted syntax to the right of the `=`.
|
||||
|
||||
在下面的例子中,`iconUrl`和`onSave`是组件的成员,它们在`=`右侧引号中的语法中被引用了。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'io-1')(format=".")
|
||||
:marked
|
||||
They are *neither inputs nor outputs* of the component. They are data sources for their bindings.
|
||||
|
@ -2246,7 +2158,6 @@ figure.image-display
|
|||
Now look at `HeroDetailComponent` when it is the **target of a binding**.
|
||||
|
||||
现在,看看`HeroDetailComponent`,它是**绑定的目标**。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'io-2')(format=".")
|
||||
:marked
|
||||
Both `HeroDetailComponent.hero` and `HeroDetailComponent.deleteRequest` are on the **left side** of binding declarations.
|
||||
|
@ -2267,7 +2178,6 @@ figure.image-display
|
|||
with decorators as input and output properties.
|
||||
|
||||
当我们深入`HeroDetailComponent`内部时,就会看到这些属性被装饰器标记成了输入和输出属性。
|
||||
|
||||
+makeExample('template-syntax/ts/app/hero-detail.component.ts', 'input-output-1')(format=".")
|
||||
|
||||
:marked
|
||||
|
@ -2284,7 +2194,6 @@ figure.image-display
|
|||
Don't do both!
|
||||
|
||||
我们既可以通过装饰器,又可以通过元数据数组来指定输入/输出属性。但别同时用!
|
||||
|
||||
:marked
|
||||
### Input or output?
|
||||
### 输入或输出?
|
||||
|
@ -2326,7 +2235,6 @@ h3#aliasing-io Aliasing input/output properties
|
|||
we expect to bind to an event property that is also called `myClick`.
|
||||
|
||||
这是使用[属性(Attribute)型指令](attribute-directives.html)时的常见情况。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'my-click')(format=".")
|
||||
:marked
|
||||
However, the directive name is often a poor choice for the name of a property within the directive class.
|
||||
|
@ -2366,13 +2274,11 @@ h3#aliasing-io Aliasing input/output properties
|
|||
:marked
|
||||
## Template expression operators
|
||||
## 模板表达式操作符
|
||||
|
||||
The template expression language employs a subset of #{_JavaScript} syntax supplemented with a few special operators
|
||||
for specific scenarios. We'll cover two of these operators: _pipe_ and _safe navigation operator_.
|
||||
|
||||
模板表达式语言使用了#{_JavaScript}语法的一个子集,并补充了几个用于特定场景的特殊操作符。
|
||||
模板表达式语言使用了JavaScript语法的一个子集,并补充了几个用于特定场景的特殊操作符。
|
||||
这里我们讲其中的两个:_管道_和_安全导航操作符_。
|
||||
// #enddocregion expression-operators
|
||||
|
||||
:marked
|
||||
<a id="pipe"></a>
|
||||
|
@ -2389,7 +2295,6 @@ h3#aliasing-io Aliasing input/output properties
|
|||
Angular[管道](./pipes.html)对像这样的小型转换来说是个明智的选择。
|
||||
管道是一个简单的函数,它接受一个输入值,并返回转换结果。
|
||||
它们很容易用于模板表达式中,只要使用**管道操作符(`|`)**就行了。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'pipes-1')(format=".")
|
||||
:marked
|
||||
The pipe operator passes the result of an expression on the left to a pipe function on the right.
|
||||
|
@ -2399,25 +2304,23 @@ h3#aliasing-io Aliasing input/output properties
|
|||
We can chain expressions through multiple pipes:
|
||||
|
||||
我们还可以通过多个管道串联出表达式:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'pipes-2')(format=".")
|
||||
:marked
|
||||
And we can also [apply parameters](./pipes.html#parameterizing-a-pipe) to a pipe:
|
||||
|
||||
我们还能[应用参数](./pipes.html#parameterizing-a-pipe)到一个管道
|
||||
|
||||
我们还能对它们使用参数:
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'pipes-3')(format=".")
|
||||
|
||||
:marked
|
||||
block json-pipe
|
||||
:marked
|
||||
The `json` pipe is particularly helpful for debugging our bindings:
|
||||
|
||||
`json`管道是特别设计来帮助我们调试绑定的:
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'pipes-json')(format=".")
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'pipes-json')(format=".")
|
||||
:marked
|
||||
The generated output would look something like this
|
||||
|
||||
生产的输出应该看起来像这样:
|
||||
它生成的输出是类似于这样的:
|
||||
code-example(language="json").
|
||||
{ "firstName": "Hercules", "lastName": "Son of Zeus",
|
||||
"birthdate": "1970-02-25T08:00:00.000Z",
|
||||
|
@ -2434,7 +2337,6 @@ h3#aliasing-io Aliasing input/output properties
|
|||
|
||||
Angular的**安全导航操作符(`?.`)**是一种流畅而便利的方式,用来保护出现在属性路径中null和undefined值。
|
||||
这意味着,当`currentHero`为空时,保护视图渲染器,让它免于失败。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'safe-2')(format=".")
|
||||
|
||||
block dart-safe-nav-op
|
||||
|
@ -2448,7 +2350,6 @@ block dart-safe-nav-op
|
|||
What happens when the following data bound `title` property is null?
|
||||
|
||||
如果下列数据绑定中`title`属性为空,会发生什么?
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'safe-1')(format=".")
|
||||
:marked
|
||||
The view still renders but the displayed value is blank; we see only "The title is" with nothing after it.
|
||||
|
@ -2465,17 +2366,13 @@ block dart-safe-nav-op
|
|||
code-example(language="html").
|
||||
The null hero's name is {{nullHero.firstName}}
|
||||
|
||||
这个空英雄的名字是{{nullHero.firstName}}
|
||||
|
||||
block null-deref-example
|
||||
:marked
|
||||
:marked
|
||||
JavaScript throws a null reference error, and so does Angular:
|
||||
|
||||
JavaScript抛出了一个空引用错误,Angular也是如此。
|
||||
code-example(format="" language="html").
|
||||
TypeError: Cannot read property 'firstName' of null in [null]
|
||||
|
||||
(类型错:无法读取null的'firstName'属性)
|
||||
JavaScript抛出了一个空引用错误,Angular也是如此:
|
||||
code-example(format="nocode").
|
||||
TypeError: Cannot read property 'firstName' of null in [null].
|
||||
|
||||
:marked
|
||||
Worse, the *entire view disappears*.
|
||||
|
@ -2508,17 +2405,15 @@ code-example(format="" language="html").
|
|||
We could code around that problem with [NgIf](#ngIf).
|
||||
|
||||
我们可以通过写[NgIf](#ngIf)代码来解决这个问题。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'safe-4')(format=".")
|
||||
|
||||
block safe-op-alt
|
||||
:marked
|
||||
:marked
|
||||
Or we could try to chain parts of the property path with `&&`, knowing that the expression bails out
|
||||
when it encounters the first null.
|
||||
|
||||
或者我们可以尝试通过`&&`来把属性路径的各部分串起来,让它在遇到第一个空值的时候,就返回空。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'safe-5')(format=".")
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'safe-5')(format=".")
|
||||
|
||||
:marked
|
||||
These approaches have merit but can be cumbersome, especially if the property path is long.
|
||||
|
@ -2527,6 +2422,7 @@ block safe-op-alt
|
|||
这些方法都有价值,但是会显得笨重,特别是当这个属性路径非常长的时候。
|
||||
想象一下在一个很长的属性路径(如`a.b.c.d`)中对空值提供保护。
|
||||
|
||||
:marked
|
||||
The Angular safe navigation operator (`?.`) is a more fluent and convenient way to guard against nulls in property paths.
|
||||
The expression bails out when it hits the first null value.
|
||||
The display is blank, but the app keeps rolling without errors.
|
||||
|
@ -2534,14 +2430,12 @@ block safe-op-alt
|
|||
Angular安全导航操作符(`?.`)是在属性路径中保护空值的一个更加流畅、便利的方式。
|
||||
表达式会在它遇到第一个空值的时候跳出。
|
||||
显示是空的,但是应用正常工作,而没有发生错误。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'safe-6')(format=".")
|
||||
:marked
|
||||
It works perfectly with long property paths such as `a?.b?.c?.d`.
|
||||
|
||||
在像`a?.b?.c?.d`这样的长属性路径中,它工作得很完美。
|
||||
|
||||
|
||||
.l-main-section
|
||||
:marked
|
||||
## Summary
|
||||
|
@ -2549,4 +2443,3 @@ block safe-op-alt
|
|||
We’ve completed our survey of template syntax. Now it's time to put that knowledge to work as we write our own components and directives.
|
||||
|
||||
我们完成了模板语法的概述。现在,我们该把如何写组件和指令的知识投入到实际工作当中了。
|
||||
|
||||
|
|
Loading…
Reference in New Issue