freeCodeCamp/guide/chinese/angular/data-binding/index.md

197 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
title: Data Binding
localeTitle: 数据绑定
---
# 数据绑定
#### 动机
数据通常定义应用程序的外观。将数据解释为用户界面涉及类逻辑( `.component.html` )和模板视图( `.component.ts` )。 Angular通过数据绑定连接它们。将数据绑定视为组件交互的工具。
#### 组件和模板
该组件将其大部分逻辑和数据存储在用`@Component`修饰的`@Component` 。此装饰器将类定义为具有模板HTML的组件。组件的模板表示应用程序中的类。这里的重点需要在组件的类和模板HTML之间。
这是数据绑定发生的地方。元素属性和事件获得指定的值。由组件类定义的这些值提供两个角色之一。一种是生成模板然后接收的数据。另一个处理模板元素发出的事件。
![代码示例](https://raw.githubusercontent.com/sosmaniac-FCC/designatedata/master/image4.png)
尝试将此图片用作下一部分的心智模型。
#### 绑定方向
绑定数据有两种方式:单向和双向。 Angular技术上只使用单向数据流。双向流动最终是单向的。它发生在两个单向流动的应用中每个方向一次。稍后会详细介绍。
单向流定义了单向交互。组件将数据发送到模板,或者模板向组件逻辑发出事件。模板范围内的数据更改不会渗透到组件类。事件发出是从模板元素开始的单向事务。
双向构成两个方向。这意味着对类逻辑或模板HTML中的数据的更改将持续存在于彼此之间。更改的范围是组件的视图。视图包含组件的类和模板。
#### 元素属性
为了识别数据绑定元素属性Angular使用特殊的括号语法。
```typescript
// my.component.ts
@Component({
templateUrl: './my.component.html'
})
export class MyComponent {
value:type = /* some value of type */;
}
```
```html
<!-- my.component.html -->
<any-element [property]=“value>innerHTML</any-element>
```
请耐心等待。
`[property]`镜像域对象模型DOM元素的对象节点中的属性。不要将对象属性与DOM元素的属性混淆。属性和属性通常共享相同的名称并执行相同的操作。然而有一个明显的区别。
请记住, `attr` attributes是底层DOM对象的单个属性。它在DOM的实例化中声明其属性值与元素的定义匹配。之后它保持相同的值。每个属性在DOM对象节点中都有自己的键值字段。这些属性在实例化后是可变的。
了解属性和属性之间的区别。这将有助于更好地理解Angular如何将数据绑定到属性属性绑定。 Angular几乎不会将数据绑定到元素的属性。例外情况非常罕见。最后一次Angular将组件数据绑定到属性而不是属性
返回参考示例,元素属性赋值中的`[ … ]`具有特殊含义。括号表示`property`在赋值右侧绑定为`“value”` 。
`value`在括号的上下文中也有特殊含义。 `value`本身就是一个字符串文字。 Angular读取它并将其值与组件类成员进行匹配。 Angular将替换匹配成员属性的值。这当然是指承载模板HTML的相同组件类。
从组件到模板的单向数据流已完成。该成员与括号内财产的正确转让相匹配,提供了`value` 。请注意组件类中成员值的更改会渗透到模板。这就是Angular在工作中的变化检测。模板范围内的更改对组件类成员没有影响。
关键要点:组件类在模板显示时提供数据。
我没有提到数据值也可以显示在组件的`innerHTML` 。最后一个示例实现了双花括号。 Angular识别这些大括号并将匹配的组件类数据插入到`div`的`innerHTML`中。
```html
<div>The value of the component class member 'value' is {{value}}.</div>
```
#### 事件处理
如果组件提供数据,则模板提供事件。
```typescript
// my.component.ts
@Component({
templateUrl: './my.component.html'
})
export class MyComponent {
handler(event):void {
// function does stuff
}
}
```
```html
// my.component.html
<any-element (event)=“handler($event)”>innerHTML</any-element>
```
这类似于属性绑定。
`(event)`适用于任何有效的事件类型。例如,最常见的事件类型之一是`click` 。 _单击_鼠标时会发出。无论类型如何, `event`都绑定到示例中的`“handler”` 。事件处理程序通常是组件类的成员函数。
`( … )`对Angular特殊。括号告诉Angular一个事件受限于正确的`handler`分配。事件本身源自host元素。
当事件发出时,它以`$event`的形式传递Event对象。 `handler`映射到组件类的同名`handler`函数。从事件绑定元素到组件类的单向交换已完成。
尽可能从处理程序中发出事件不会影响模板元素。毕竟绑定是单向的。
#### 双向绑定
输入表单提供了为什么需要双向绑定的一个很好的例子。双向数据绑定比事件或属性绑定更昂贵。
双向数据绑定有自己的模块。在考虑之前,请考虑以下示例。
```typescript
// my.component.ts
@Component({
templateUrl: './my.component.html'
})
export class MyComponent {
inputValue:string = "";
handler(event) {
this.inputValue = event.target.value;
}
}
```
```html
<!-- my.component.html -->
<input (input)=“handler($event)” [value]=“inputValue>
```
是时候打破这个了。
这个例子结合了前两个。这就解释了为什么它成本更高。遵循逻辑,假设用户在输入元素中键入内容。元素向模板的组件类的`handler`发出`input`事件。处理程序将类成员`inputValue`分配给发出的事件的值。这结束了事件处理/绑定。
现在进入属性绑定。为`inputValue`分配了一个新值。由于`inputValue`绑定到input元素的`value` 因此其数据更改会渗透到input元素的`value`属性中。 input元素的`value`与`inputValue`匹配。结束了属性绑定。
你有它。双向数据绑定发生在连续应用单向绑定的两个应用程序中。但语法有点乱。
值得庆幸的是Angular提供了`NgModel`来简化语法。以下示例与上述内容同义。
```typescript
// my.component.ts
@Component({
templateUrl: './my.component.html'
})
export class MyComponent {
inputValue:string = "";
}
```
```html
<!-- my.component.html -->
<input [(ngModel)]=“inputValue>
```
`ngModel`是一个很好的方便。在使用之前您必须在应用程序的根目录中导入FormsModule。通过这种平方双向数据绑定变得更容易使用。
为了加强您所学到的知识,请查看官方[Angular文档1中的](https://angular.io/guide/architecture-components#data-binding)这张图片。
![数据流图](https://raw.githubusercontent.com/sosmaniac-FCC/designatedata/master/image2.png)
到目前为止,您可以使用此图片直观地总结所有内容。 Angular的文档还有很多其他值得一看的图片。鉴于本文的范围这个应该足够了。
#### 组件到组件
要跨不同组件绑定数据和事件,必须使用@Input和@Output装饰器。角度组件是私有范围的。组件的所有成员都不能从其原生视图之外的任何位置访问。
@Input装饰器指示成员的值来自父函数。这需要可视化以更好地理解。
![代码示例](https://raw.githubusercontent.com/sosmaniac-FCC/designatedata/master/image3_.png)
请注意将父级的`value`成员传递给子级的`property`成员。如果`property`没有@Input装饰器那么这是不可能的。 Angular编译器依赖于它。
@Output的另一个示例显示了事件如何从子项传播到父项。请记住,@ Output几乎总是与自定义事件绑定有关。
![代码示例](https://raw.githubusercontent.com/sosmaniac-FCC/designatedata/master/image1.png)
如果要复制其中任何一个示例,请确保从`@angular/common`导入`EventEmitter` `@angular/common` `@Input`和`@Output` 。
#### 结论
这是一个停下来的好地方。数据绑定涵盖了大量用例。这个主题值得在[Angular的网站](https://angular.io)上进一步探讨。这些不是您在Angular中操作数据的唯一方法。有关更多信息请参阅参考资料下的链接
### 来源
1. [角度团队。组件简介。谷歌。 2018年5月26日访问](https://angular.io/guide/architecture-components#data-binding)
### 资源
* [角度文档](https://angular.io/docs)
* [Angular GitHub存储库](https://github.com/angular/angular)
* [有关Angular中的组件和模板的更多信息](https://angular.io/guide/displaying-data)