Polish user-input.jade (round 2)

This commit is contained in:
Yang Lin 2016-12-01 00:48:23 +08:00
parent f164b9cf0e
commit 1874c5147c
1 changed files with 73 additions and 67 deletions

View File

@ -6,8 +6,8 @@ include ../_util-fns
This page explains how to bind those events to component event handlers using the Angular
event binding syntax.
当用户点击链接、按下按钮或者输入文字时,我们得知道发生了什么。这些用户动作都会产生DOM事件。
本章我们将学习如何使用Angular事件绑定语法来绑定这些事件
当用户点击链接、按下按钮或者输入文字时,这些用户动作都会产生 DOM 事件。
本章解释如何使用 Angular 事件绑定语法把这些事件绑定到事件处理器
Run the <live-example></live-example>.
@ -23,18 +23,17 @@ include ../_util-fns
Many DOM events are triggered by user input. Binding to these events provides a way to
get input from the user.
你可以使用[Angular事件绑定](./template-syntax.html#event-binding)机制来响应任何[DOM事件](https://developer.mozilla.org/en-US/docs/Web/Events)。
许多DOM事件被用户输入所触发。绑定这些事件提供了获取用户输入的方法
你可以使用 [Angular 事件绑定](./template-syntax.html#event-binding)机制来响应任何 [DOM 事件](https://developer.mozilla.org/en-US/docs/Web/Events)。
许多 DOM 事件是由用户输入触发的。绑定这些事件可以获取用户输入
To bind to a DOM event, surround the DOM event name in parentheses and assign a quoted
[template statement](./template-syntax.html#template-statements) to it.
为了绑定DOM事件只要把DOM事件的名字包裹在圆括号中然后用一个放在引号中的[模板语句](./template-syntax.html#template-statements)对它赋值就可以了。
要绑定 DOM 事件,只要把 DOM 事件的名字包裹在圆括号中,然后用放在引号中的[模板语句](./template-syntax.html#template-statements)对它赋值就可以了。
The following example shows an event binding that implements a click handler:
下面的例子中,用事件绑定实现点击事件处理器:
下例展示了一个事件绑定,它实现了一个点击事件处理器:
+makeExample('user-input/ts/app/click-me.component.ts', 'click-me-button')(format=".", language="html")
@ -45,51 +44,53 @@ include ../_util-fns
is the **template statement**, which reponds
to the click event by calling the component's `onClickMe` method.
等号左边的`(click)`表示把按钮的点击事件作为**绑定目标**。
等号右边引号中的文本是**模板语句**在这里我们通过调用组件的`onClickMe`方法来响应这个点击事件。
等号左边的`(click)`表示把按钮的点击事件作为**绑定目标**。
等号右边引号中的文本是**模板语句**,通过调用组件的`onClickMe`方法来响应这个点击事件。
When writing a binding, be aware of a template statement's **execution context**.
The identifiers in a template statement belong to a specific context object,
usually the Angular component controlling the template.
The example above shows a single line of HTML, but that HTML belongs to a larger component:
写绑定时,我们必须知道模板语句的**执行上下文**。
写绑定时,需要知道模板语句的**执行上下文**。
出现在模板语句中的每个标识符都属于特定的上下文对象。
这个对象通常都是控制此模板的Angular组件在本例中它很明确因为这段HTML片段属于下面这个组件
这个对象通常都是控制此模板的 Angular 组件。
上例中只显示了一行 HTML那段 HTML 片段属于下面这个组件:
+makeExample('user-input/ts/app/click-me.component.ts', 'click-me-component', 'app/click-me.component.ts')(format=".")
:marked
When the user clicks the button, Angular calls the `onClickMe` method from `ClickMeComponent`.
当用户点击此按钮时Angular调用组件的`onClickMe`方法。
当用户点击按钮时Angular 调用`ClickMeComponent`的`onClickMe`方法。
.l-main-section
:marked
## Get user input from the $event object
## 通过$event对象取得用户输入
## 通过 $event 对象取得用户输入
DOM events carry a payload of information that may be useful to the component.
This section shows how to bind to the `keyup` event of an input box to get the user's input after each keystroke.
DOM事件承载可能对组件有用的信息的有效荷载
本节将展示如何绑定`keyup`事件到一个输入框中用来在每个键盘敲击时获取用户输入。
DOM 事件可以携带可能对组件有用的信息
本节将展示如何绑定输入框的`keyup`事件,在每个敲击键盘时获取用户输入。
The following code listens to the `keyup` event and passes the entire event payload (`$event`) to the component event handler.
下面的代码监听`keyup`事件并将整个事件的有效荷载 (`$event`) 传递给组件的事件处理器。
下面的代码监听`keyup`事件,并将整个事件载荷 (`$event`) 传递给组件的事件处理器。
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-1-template', 'app/keyup.components.ts (template v.1)')(format=".")
:marked
When a user presses and releases a key, the `keyup` event occurs, and Angular provides a corresponding
DOM event object in the `$event` variable which this code passes as a parameter to the component's `onKey()` method.
当用户按下并释放一个按键时,`keyup`事件触发Angular 提供一个对应的DOM事件对象`$event`,该代码将其作为参数传递给`onKey()`方法。
当用户按下并释放一个按键时,触发`keyup`事件Angular 在`$event`变量提供一个相应的 DOM
事件对象,上面的代码将它作为参数传递给`onKey()`方法。
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-1-class-no-type', 'app/keyup.components.ts (类 v.1)')(format=".")
:marked
The properties of an `$event` object vary depending on the type of DOM event. For example,
a mouse event includes different information than a input box editing event.
`$event`对象的属性根据DOM事件的类型个不相同。例如鼠标事件于输入框编辑事件包含了不同的信息。
`$event`对象的属性取决于 DOM 事件的类型。例如,鼠标事件与输入框编辑事件包含了不同的信息。
All [standard DOM event objects](https://developer.mozilla.org/en-US/docs/Web/API/Event)
have a `target` property, a reference to the element that raised the event.
@ -97,23 +98,23 @@ include ../_util-fns
`event.target.value` returns the current contents of that element.
所有[标准 DOM 事件对象](https://developer.mozilla.org/en-US/docs/Web/API/Event)都有一个`target`属性,
它代表了触发该事件的元素。
在本例中,`target`是[`<input>`元素](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement)对象
而且`value.target.value`返回该元素的当前内容。
引用触发该事件的元素。
在本例中,`target`是[`<input>`元素](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement)
`value.target.value`返回该元素的当前内容。
After each call, the `onKey()` method appends the contents of the input box value to the list
in the component's `values` property, followed by a separator character (|).
The [interpolation](./template-syntax.html#interpolation)
displays the accumulating input box changes from the `values` property.
在组件的`onKey()`方法中,先从事件对象提取出用户输入,再把输入的值累加组件的`values`属性里,我们利用这个属性来累计用户数据
然后我们使用[插值表达式](./template-syntax.html#interpolation)来把存放累加结果的`values`属性回显到屏幕上。
在组件的`onKey()`方法中,把输入框的值和分隔符 (|) 追加组件的`values`属性
使用[插值表达式](./template-syntax.html#interpolation)来把存放累加结果的`values`属性回显到屏幕上。
Suppose the user enters the letters "abc", and then backspaces to remove them one by one.
Here's what the UI displays:
假设用户输入字母"abc",然后用退格键删除它们。
界面上的显示如下
假设用户输入字母"abc",然后用退格键一个一个删除它们。
用户界面将显示
code-example().
a | ab | abc | ab | a | |
figure.image-display
@ -124,7 +125,7 @@ figure.image-display
Alternatively, you could accumulate the individual keys themselves by substituting `event.key`
for `event.target.value` in which case the same user input would produce:
另外,你可以通过用`event.key`来为`event.target.value`积累各个按键本身,这样同样的用户输入可以产生:
或者,你可以用`event.key`替代`event.target.value`积累各个按键本身,这样同样的用户输入可以产生:
code-example().
a | b | c | backspace | backspace | backspace |
@ -141,11 +142,11 @@ a#keyup1
上例将`$event`转换为`any`类型。
这样简化了代码,但是有成本。
没有任何类型信息来显示事件对象的属性并防止简单的错误。
没有任何类型信息能够揭示事件对象的属性,防止简单的错误。
The following example rewrites the method with types:
下面的例子用`type`重写了该方法:
下面的例子,使用了带类型方法:
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-1-class', 'app/keyup.components.ts (class v.1 - typed )')(format=".")
:marked
@ -155,11 +156,11 @@ a#keyup1
`$event`的类型现在是`KeyboardEvent`。
不是所有的元素都有`value`属性,所以它将`target`转换为输入元素。
`OnKey`方法更加清晰的显示了它从模板中期待什么,以及它是如何解析事件的。
`OnKey`方法更加清晰的表达了它期望从模板得到什么,以及它是如何解析事件的。
### Passing _$event_ is a dubious practice
### 传入*$event*是可疑的做法
### 传入 *$event* 是靠不住的做法
Typing the event object reveals a significant objection to passing the entire DOM event into the method:
the component has too much awareness of the template details.
@ -167,13 +168,13 @@ a#keyup1
That breaks the separation of concerns between the template (_what the user sees_)
and the component (_how the application processes user data_).
类型化事件对象揭露了重要的一点,即反对把整个DOM事件传到方法中。因为这样组件会知道太多模板的信息。
只有当它了解一些它本不需要了解的 HTML 实现细节时,它才能提取信息。
类型化事件对象揭露了重要的一点,即反对把整个 DOM 事件传到方法中,因为这样组件会知道太多模板的信息。
只有当它知道更多它本不应了解的 HTML 实现细节时,它才能提取信息。
这就违反了模板(*用户看到的*)和组件(*应用如何处理用户数据*)之间的分离关注原则。
The next section shows how to use template reference variables to address this problem.
下面将介绍如何用模板引用变量来处理这个问题。
下面将介绍如何用模板引用变量来解决这个问题。
.l-main-section
:marked
@ -186,9 +187,9 @@ a#keyup1
These variables provide direct access to an element from within the template.
To declare a template reference variable, precede an identifier with a hash (or pound) character (#).
还有另一种获取用户数据的方式:使用 Angular 的[**模板引用变量**](./template-syntax.html#ref-vars)的语法特性
这些变量给了我们直接访问元素的能力。
通过在标识符前加上井号(#),我们就能定义一个模板引用变量。
还有另一种获取用户数据的方式:使用 Angular 的[**模板引用变量**](./template-syntax.html#ref-vars)。
这些变量提供了从模块中直接访问元素的能力。
在标识符前加上井号 (#) 就能声明一个模板引用变量。
The following example uses a template reference variable
to implement a keystroke loopback in a simple template.
@ -201,13 +202,13 @@ a#keyup1
The code uses the `box` variable to get the input element's `value` and display it
with interpolation between `<p>` tags.
我们在`<input>`元素上定义了一个名叫`box`的模板引用变量
`box`变量引用的就是`<input>`元素本身这意味着我们可以获得input元素的`value`值,并通过插值表达式把它显示在`<p>`标签中。
这个模板引用变量名叫`box`,在`<input>`元素声明,它引用`<input>`元素本身
代码使用`box`获得输入元素的`value`值,并通过插值表达式把它显示在`<p>`标签中。
The template is completely self contained. It doesn't bind to the component,
and the component does nothing.
这个模板完全是完全自包含的。它没有绑定到组件,组件没做任何事情。
这个模板完全是完全自包含的。它没有绑定到组件,组件没做任何事情。
Type something in the input box, and watch the display update with each keystroke.
@ -219,39 +220,39 @@ figure.image-display
:marked
**This won't work at all unless you bind to an event**.
**我们必须绑定一个事件,否则这将完全无法工作。**
**除非你绑定一个事件,否则这将完全无法工作。**
Angular updates the bindings (and therefore the screen)
only if the app does something in response to asynchronous events, such as keystrokes.
只有在应用做了些异步事件(如击键)Angular才更新绑定(并最终影响到屏幕)
只有在应用做了些异步事件如击键Angular 才更新绑定(并最终影响到屏幕)
This example code binds the `keyup` event
to the number 0, the shortest template statement possible.
While the statement does nothing useful,
it satisfies Angular's requirement so that Angular will update the screen.
本例代码将`keyup`事件绑定到了数字0这是我们所能想到的最短语句。
虽然这个声明不做什么,它满足 Angular 的要求,所以 Angular 将更新屏幕。
本例代码将`keyup`事件绑定到了数字0这是可能是最短的模板语句。
虽然这个语句不做什么,但它满足 Angular 的要求,所以 Angular 将更新屏幕。
:marked
It's easier to get to the input box with the template reference
variable than to go through the `$event` object. Here's a rewrite of the previous
`keyup` example that uses a template reference variable to get the user's input.
从模板变量获得输入框比通过`$event`对象更加简单。
下面是之前`keyup`例子的新版本,它使用变量来获得用户输入。
下面的代码重写了之前`keyup`示例,它使用变量来获得用户输入。
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-2' ,'app/keyup.components.ts (v2)')(format=".")
:marked
A nice aspect of this approach is that the component gets clean data values from the view.
It no longer requires knowledge of the `$event` and its structure.
看起来真是简单多了。
这个方法最漂亮的一点是:我们的组件代码从视图中获得了干干净净的数据值。再也不用了解`$event`变量及其结构了。
这个方法最漂亮的一点是:组件代码从视图中获得了干净的数据值。再也不用了解`$event`变量及其结构了。
<a id="key-event"></a>
.l-main-section
:marked
## Key event filtering (with `key.enter`)
## 按键事件过滤(通过`key.enter`
The `(keyup)` event handler hears *every keystroke*.
@ -259,14 +260,14 @@ figure.image-display
One way to reduce the noise would be to examine every `$event.keyCode` and take action only when the key is _Enter_.
`(keyup)`事件处理器监听*每一次按键*。
有时我们只在意*回车*键是否被敲过,因为这标志着用户结束了输入。
解决这个问题的一种方法是检查每个`$event.keyCode`,只有当*回车*键被敲入时才采取行动。
有时只在意*回车*键,因为它标志着用户结束输入。
解决这个问题的一种方法是检查每个`$event.keyCode`,只有键值是*回车*键时才采取行动。
There's an easier way: bind to Angular's `keyup.enter` pseudo-event.
Then Angular calls the event handler only when the user presses _Enter_.
更简单的方法是:绑定到 Angular 的`keyup.enter` 模拟事件。
然后,只有当用户敲*回车*键时Angular才会调用事件处理器。
然后,只有当用户敲*回车*键时Angular 才会调用事件处理器。
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-3' ,'app/keyup.components.ts (v3)')(format=".")
:marked
@ -279,19 +280,20 @@ figure.image-display
.l-main-section
:marked
## On blur
## 失去焦点事件blur
## 失去焦点事件 (blur)
In the previous example, the current state of the input box
is lost if the user mouses away and clicks elsewhere on the page
without first pressing _Enter_.
The component's `value` property is updated only when the user presses _Enter_.
一个例子中,如果用户移开了鼠标,并且点击了页面中别的地方,它不会传出输入框的值
只有在输入框得到焦点,并且用户按下了回车键的时候,我们才能更新组件的`values`属性
上例中,如果用户没有先按回车键,而是移开了鼠标,点击了页面中其它地方,输入框的当前值就会丢失
只有当用户按下了回车键候,组件的`values`属性才能更新
To fix this issue, listen to both the _Enter_ key and the _blur_ event.
我们来修正这个问题 —— 通过同时监听输入框的失去焦点事件
下面通过同时监听输入框的回车键和失去焦点事件来修正这个问题
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-4' ,'app/keyup.components.ts (v4)')(format=".")
@ -303,17 +305,16 @@ figure.image-display
The previous page showed how to [display data](./displaying-data.html).
This page demonstrated event binding techniques.
在前一章中,我们学到了如何[显示数据](./displaying-data.html)。
在本章中,我们得到了一个关于事件绑定技术的小型武器库。
上一章介绍了如何[显示数据](./displaying-data.html)。
本章展示了事件绑定技术。
Now, put it all together in a micro-app
that can display a list of heroes and add new heroes to the list.
The user can add a hero by typing the hero's name in the input box and
clicking **Add**.
让我们在一个微型应用中把它们放在一起,它能显示一个英雄列表,并把新的英雄加到列表中。
用户可以通过下列步骤添加英雄:先在输入框中输入,然后按下回车键、点击“添加”按钮或点击页面中的其它地方
现在,在一个微型应用中一起使用它们,应用能显示一个英雄列表,并把新的英雄加到列表中。
用户可以通过输入英雄名和点击“添加”按钮来添加英雄
figure.image-display
img(src='/resources/images/devguide/user-input/little-tour-anim.gif' alt="简版英雄指南")
@ -331,30 +332,34 @@ figure.image-display
The `newHero` template variable refers to the `<input>` element.
You can reference `newHero` from any sibling or child of the `<input>` element.
* **使用模板变量来引用元素** —`newHero`模板变量引用了`<input>`元素。
你可以在`<input>`的任何兄弟或子级元素中使用`newHero`。
**使用模板变量来引用元素** &mdash; `newHero`模板变量引用了`<input>`元素。
你可以在`<input>`的任何兄弟或子级元素中用`newHero`。
* **Pass values, not elements** &mdash;
Instead of passing the `newHero` into the component's `addHero` method,
get the input box value and pass *that* to `addHero`.
* **传递数值,而非元素** — 获取输入框的值并将*它*传递给组件的`addHero`,而不要传递`newHero`。
**传递数值,而非元素** &mdash;
获取输入框的值并将*它*传递给组件的`addHero`,而不要传递`newHero`。
* **Keep template statements simple** &mdash;
The `(blur)` event is bound to two JavaScript statements.
The first statement calls `addHero`. The second statement, `newHero.value=''`,
clears the input box after a new hero is added to the list.
* **保持模板语句简单** — `(blur)`事件被绑定到两个 JavaScript 语句。第一句调用`addHero`。第二句`newHero.value=''`在添加新英雄到列表中后清除输入框。
**保持模板语句简单** &mdash;
`(blur)`事件被绑定到两个 JavaScript 语句。
第一句调用`addHero`。第二句`newHero.value=''`在添加新英雄到列表中后清除输入框。
.l-main-section
:marked
## Source code
## 源码
## 源代码
Following is all the code discussed in this page.
下面是我们在本章讨论过的所有源码。
下面是本章讨论过的所有源码。
+makeTabs(`
user-input/ts/app/click-me.component.ts,
user-input/ts/app/keyup.components.ts,
@ -369,6 +374,7 @@ figure.image-display
.l-main-section
:marked
## Summary
## 小结
You have mastered the basic primitives for responding to user input and gestures.
@ -382,8 +388,8 @@ figure.image-display
The next page, `Forms`, explains how to write
two-way bindings with `NgModel`.
这些技术对小规模演示很实用,但是在处理大量用户输入时很容易变得累赘和笨拙。
双向数据绑定是更加优雅和简洁的在数据输入区域和模型属性之间传递数据的方式。
下一`表单`解释了如何用`NgModel`来进行双向绑定。
这些技术对小规模演示很实用,但是在处理大量用户输入时很容易变得累赘和笨拙。
要在数据录入字段和模型属性之间传递数据,双向数据绑定是更加优雅和简洁的方式。
下一`表单`解释了如何用`NgModel`来进行双向绑定。