From 7f6a9be1eef95db39820752c128948759e2b8f4d Mon Sep 17 00:00:00 2001 From: Rex Date: Mon, 18 Apr 2016 17:02:14 +0100 Subject: [PATCH] a bit more work on component-communication.jade. --- .../cookbook/component-communication.jade | 88 +++++++++++++++++-- .../docs/ts/latest/cookbook/dynamic-form.jade | 2 +- 2 files changed, 82 insertions(+), 8 deletions(-) diff --git a/public/docs/ts/latest/cookbook/component-communication.jade b/public/docs/ts/latest/cookbook/component-communication.jade index cbb8580c36..ff0ce7f96f 100644 --- a/public/docs/ts/latest/cookbook/component-communication.jade +++ b/public/docs/ts/latest/cookbook/component-communication.jade @@ -88,7 +88,7 @@ figure.image-display ### 测试 E2E test that all children were instantiated and displayed as expected: - 重头到脚的测试,确认所有子级初始化和显示的和我们预期的一样。 + 端对端测试,以确认所有子级初始化和显示的和我们预期的一样。 +makeExample('cb-component-communication/e2e-spec.js', 'parent-to-child') @@ -110,12 +110,14 @@ figure.image-display The setter of the `name` input property in the child `NameChildComponent` trims the whitespace from a name and replaces an empty value with default text. - 这个 + 这个在子组件`NameChildComponent`的`name` Input属性的setter,修剪名字里面的空格和替换空值为默认文字。 +makeExample('cb-component-communication/ts/app/name-child.component.ts') :marked Here's the `NameParentComponent` demonstrating name variations including a name with all spaces: + + 下面的`NameParentComponent`展示了各种名字的处理,包括一个全是空格的名字。 +makeExample('cb-component-communication/ts/app/name-parent.component.ts') @@ -127,121 +129,173 @@ figure.image-display E2E tests of input property setter with empty and non-empty names: + 端对端测试Input属性的setter,使用空名字和非空名字。 + +makeExample('cb-component-communication/e2e-spec.js', 'parent-to-child-setter') :marked [Back to top](#top) + + [回到顶部](#top) .l-main-section :marked ## Intercept input property changes with *ngOnChanges* + ## 通过*ngOnChanges*来截听Input属性值得变化 Detect and act upon changes to input property values with the `ngOnChanges` method of the `OnChanges` lifecycle hook interface. + + 使用`ngOnChanges`函数方法和`OnChanges`生命周期接口来监测Input属性值得变化并回应。 + .l-sub-section :marked May prefer this approach to the property setter when watching multiple, interacting input properties. + 当监听多个互动Input属性的时候,本方法比属性setter更合适。 + Learn about `ngOnChanges` in the [LifeCycle Hooks](../guide/lifecycle-hooks.html) chapter. + + 在[生命周期钩子](../guide/lifecycle-hooks.html)章节学习更多关于`ngOnChanges`的知识。 + :marked This `VersionChildComponent` detects changes to the `major` and `minor` input properties and composes a log message reporting these changes: + 这个`VersionChildComponent`监测`major`和`minor`Input属性的变化,并根据这些变化编写一个日志信息报告。 + +makeExample('cb-component-communication/ts/app/version-child.component.ts') :marked The `VersionParentComponent` supplies the `minor` and `major` values and binds buttons to methods that change them. + `VersionParentComponent`提供`minor`和`major`值,将变换他们值得函数方法绑定到按钮上。 + +makeExample('cb-component-communication/ts/app/version-parent.component.ts') :marked Here's the output of a button-pushing sequence: + 下面是按钮被点击的结果。 + figure.image-display img(src="/resources/images/cookbooks/component-communication/parent-to-child-on-changes.gif" alt="Parent-to-child-onchanges") :marked ### Test it + ### 测试 Test that ***both*** input properties are set initially and that button clicks trigger the expected `ngOnChanges` calls and values: + 测试两个Input属性都被初始化并在按钮被点击后,`ngOnChanges`调用和值的变化按预期进行。 + +makeExample('cb-component-communication/e2e-spec.js', 'parent-to-child-onchanges') :marked [Back to top](#top) - + [回到顶部](#top) .l-main-section :marked ## Parent listens for child event - + ## 父级监听子级事件 + The child component exposes an `EventEmitter` property with which it `emits`events when something happens. The parent binds to that event property and reacts to those events. + 子级组件暴露一个`EventEmitter`属性,利用该属性,当有事情发生时,子级组件`散发`事件。父级绑定这个事件属性并作出回应。 + The child's `EventEmitter` property is an ***output property***, typically adorned with an [@Output decoration](../guide/template-syntax.html#inputs-outputs) as seen in this `VoterComponent`: + + 子级组件的`EventEmitter`属性是一个**Output属性**,通常被[@Output装饰器](../guide/template-syntax.html#inputs-outputs)来装饰,正如在`VoterComponent`中所见。 +makeExample('cb-component-communication/ts/app/voter.component.ts') :marked Clicking a button triggers emission of a `true` or `false` (the boolean *payload*). + 点击一个按钮触发一个`true`或`false`的事件(布尔酬载) + The parent `VoteTakerComponent` binds an event handler (`onVoted`) that responds to the child event payload (`$event`) and updates a counter. + 父级`VoteTakerComponent`绑定一个事件处理器(`onVoted`),用来回应子组件时间酬载(`$event`)更新一个计数器。 + +makeExample('cb-component-communication/ts/app/votetaker.component.ts') :marked The framework passes the event argument — represented by `$event` — to the handler method, and the method processes it: + 框架(Angular)传递用`$event`代表的事件参数给事件处理器函数方法,由这个函数方法来处理: + figure.image-display img(src="/resources/images/cookbooks/component-communication/child-to-parent.gif" alt="Child-to-parent") :marked ### Test it - + ### 测试 Test that clicking the *Agree* and *Disagree* buttons update the appropriate counters: + 测试点击*Agree*和*Disagree*按钮时,计数器更新是否正确。 + +makeExample('cb-component-communication/e2e-spec.js', 'child-to-parent') :marked - [Back to top](#top) - + [Back to top](#top) + [回到顶部](#top) + parent-to-child-local-var .l-main-section :marked ## Parent interacts with child via *local variable* + ## 父级与子级通过本地变量local variable互动 A parent component cannot use data binding to read child properties or invoke child methods. We can do both by creating a template local variable for the child element and then reference that variable *within the parent template* as seen in the following example. + + 一个父级组件不能使用数据绑定来读取子级属性或者调用子级函数方法。我们可以在父级模板里,新建一个本地变量来代表子组件,然后实用这个变量来读取子级属性和调用子级函数方法,如下例所示。 We have a child `CountdownTimerComponent` that repeatedly counts down to zero and launches a rocket. It has `start` and `stop` methods that control the clock and it displays a countdown status message in its own template. + + + 我们有一个子级组件`CountdownTimerComponent`,他反复的倒计时到零,然后发射一个导弹。他有一个`start`和`stop`方法,用来控制时间和在自己的模板里面显示一个倒计时状态的信息。 +makeExample('cb-component-communication/ts/app/countdown-timer.component.ts') :marked Let's see the `CountdownLocalVarParentComponent` that hosts the timer component. + 让我们来看看计时器组件的寄主组件`CountdownLocalVarParentComponent`。 + +makeExample('cb-component-communication/ts/app/countdown-parent.component.ts', 'lv') :marked The parent component cannot data bind to the child's `start` and `stop` methods nor to its `seconds` property. + 父级组件不能数据绑定到子级的`start`和`stop`方法,也不能绑定到子级的`seconds`属性 + We can place a local variable (`#timer`) on the tag (``) 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`)放到(``)标签中,用来代表子级组件。这样我们就在父级组件获取子级组件的引用载体,在父级组件内访问子级的所有属性和方法。 In this example, we wire parent buttons to the child's `start` and `stop` and use interpolation to display the child's `seconds` property. + 在这个例子中,我们把父级组件的按钮链接到子级的`start`和`stop`方法,并用插值表达式来显示子级的`seconds`属性。 + Here we see the parent and child working together. + + 在这里我们看到父级和子级一起工作。 figure.image-display img(src="/resources/images/cookbooks/component-communication/countdown-timer-anim.gif" alt="countdown timer") @@ -249,44 +303,64 @@ figure.image-display a(id="countdown-tests") :marked ### Test it + ### 测试 Test that the seconds displayed in the parent template match the seconds displayed in the child's status message. Test also that clicking the *Stop* button pauses the countdown timer: + 测试在父级模板中显示的秒钟和子级组件里的状态信息里面的秒钟的对应。 + +makeExample('cb-component-communication/e2e-spec.js', 'countdown-timer-tests') :marked [Back to top](#top) + [回到顶部](#top) .l-main-section :marked ## Parent calls a *ViewChild* + ## 父级调用一个*ViewChild* The *local variable* approach is simple and easy. But it is limited because the parent-child wiring must be done entirely within the parent template. The parent component *itself* has no access to the child. + 上面*本地变量*的方法是一个简单和方便的方法。但是它有局限性,因为父级-子级的连接必须要全部都在父级的模板里面进行。父级组件本身对子级没有访问权。 + 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*,***注入***到父级组件里面。 + 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. + + 我们将会用一样的[倒计时](#countdown-timer-example)例子来解释这种技巧。 + 我们不会变化它的样子或行为。子级[CountdownTimerComponent](#countdown-timer-example)和原来也一样。 .l-sub-section :marked We are switching from the *local variable* to the *ViewChild* technique solely for the purpose of demonstration. + + 我们由*本地变量*切换到*ViewChild*技巧的唯一目的是做示范。 :marked Here is the parent, `CountdownViewChildParentComponent`: + + 这个是父级,`CountdownViewChildParentComponent`: +makeExample('cb-component-communication/ts/app/countdown-parent.component.ts', 'vc') :marked It takes a bit more work to get the child view into the parent component classs. + + We import references to the `ViewChild` decorator and the `AfterViewInit` lifecycle hook. We inject the child `CountdownTimerComponent` into the private `_timerComponent` property diff --git a/public/docs/ts/latest/cookbook/dynamic-form.jade b/public/docs/ts/latest/cookbook/dynamic-form.jade index 091b203616..c6c7853167 100644 --- a/public/docs/ts/latest/cookbook/dynamic-form.jade +++ b/public/docs/ts/latest/cookbook/dynamic-form.jade @@ -28,7 +28,7 @@ include ../_util-fns :marked ## Table of contents - ## 目录 + ## 目录 [问卷问题模型Question Model](#object-model) [表单组件Form Component](#form-component)