数据绑定
Angular 提供了各种各样的数据绑定,绑定的类型可以根据数据流的方向分成三类: 从数据源(类文件中的数据)到视图(模版文件的显示)、从视图(模版文件的显示)到数据源(类文件中的数据)以及双向的从视图(模版文件的显示)到数据源(类文件中的数据)再到视图(模版文件的显示)。
| 数据方向 |
语法 |
绑定类型 |
| 单向:从数据源--->视图 |
{{expression}}
<pre class="has">
[target]="expression"
<pre class="has">
bind-target="expression"
<p> </p>
</td>
<td>插值表达式<br />
属性<br />
Attribute<br />
CSS 类<br />
样式</td>
</tr><tr><td>单向:从视图--->数据源</td>
<td>
<pre class="has">
(target)="statement"
<pre class="has">
on-target="statement"
<p> </p>
</td>
<td>事件</td>
</tr><tr><td>双向:从视图<--->数据源</td>
<td>
<pre class="has">
[(target)]="expression"
<pre class="has">
bindon-target="expression"
<p> </p>
</td>
<td>双向绑定</td>
</tr></tbody></table><h2>在Angular中一旦开始数据绑定,就跟 HTML attribute 没有什么关系了。 </h2>
HTML attribute 与 DOM property 的对比
attribute 是由 HTML 定义的。property 是由 DOM (Document Object Model) 定义的。
-
有很少的一部分 HTML attribute 和 property 之间有着 1:1 的映射,如 id。
-
有些 HTML attribute 没有对应的 property,如 colspan。
-
有些 DOM property 没有对应的 attribute,如 textContent。
有很多 HTML attribute 看起来映射到了 property,但是其中的含义并不是看起来的那么简单。
attribute 初始化 DOM property,然后它们的任务就完成了。property 的值可以改变;attribute 的值不能改变。
例如,当浏览器渲染 <input type="text" value="Bob"> 时,它将创建相应 DOM 节点, 它的 value 这个 property 被初始化为 “Bob”。
当用户在输入框中输入 “Sally” 时,DOM 元素的 value 这个 property 变成了 “Sally”。 但是该 HTML 的 value 这个 attribute 保持不变。如果你读取 input 元素的 attribute,就会发现确实没变: input.getAttribute('value') // 返回 "Bob"。
HTML 的 value 这个 attribute 指定了初始值;DOM 的 value 这个 property 是当前值。
注意:disabled 这个 attribute 是另一种特例。
按钮的 disabled 这个 property 是 false,因为默认情况下按钮是可用的。 当你添加 disabled 这个 attribute 时,只要它出现了按钮的 disabled 这个 property 就初始化为 true,于是按钮就被禁用了。
添加或删除 disabled 这个 attribute 会禁用或启用这个按钮。但 attribute 的值无关紧要,这就是你为什么没法通过 <button disabled="false">仍被禁用</button> 这种写法来启用按钮。
设置按钮的 disabled 这个 property(如,通过 Angular 绑定)可以禁用或启用这个按钮。 这就是 property 的价值。
所以,就算名字相同,HTML attribute 和 DOM property 也不是同一样东西。
注意:模板绑定是通过 DOM property 和事件来工作的,而不是HTML attribute。
在 Angular 的中,HTML attribute 唯一的作用是用来初始化元素和指令的状态。 当进行数据绑定时,只是在与元素和指令的 property 和事件打交道,和attribute就完全没有关系了。
绑定目标
数据绑定的目标是 DOM 中的某些东西。 这个目标可能是(元素 | 组件 | 指令的)property、(元素 | 组件 | 指令的)事件,或(极少数情况下) attribute 名。
| 绑定类型 |
目标 |
数据流向 |
范例 |
|---|
| 属性 |
元素的property
组件的 property
指令的 property |
单向绑定,
<p>数据:</p>
<p>数据源->模版</p>
</td>
<td style="width:525px;">
<pre class="has">
<img [src]="heroImageUrl">
<pre class="has">
<app-hero-detail [hero]="currentHero"></app-hero-detail>
<pre class="has">
<div [ngClass]="{'special': isSpecial}"></div>
<p> </p>
</td>
</tr><tr><td>事件</td>
<td style="width:125px;">元素的事件<br />
组件的事件<br />
指令的事件</td>
<td style="width:130px;">
<p>单向绑定,</p>
<p>数据:</p>
<p>模版->数据源</p>
</td>
<td style="width:525px;">
<pre class="has">
<button (click)="onSave()">Save</button>
<pre class="has">
<app-hero-detail (deleteRequest)="deleteHero()"></app-hero-detail>
<pre class="has">
<div (myClick)="clicked=$event" clickable>click me</div>
<p> </p>
</td>
</tr><tr><td>
<p>双向</p>
</td>
<td style="width:125px;">
<p>事件与 property</p>
</td>
<td style="width:130px;">
<p>双向绑定,</p>
<p>数据:</p>
<p>模版<---->数据源</p>
</td>
<td style="width:525px;">
<pre class="has">
<input [(ngModel)]="name">
<p> </p>
</td>
</tr><tr><td>
<p>Attribute</p>
</td>
<td style="width:125px;">
<p>attribute(例外情况)</p>
</td>
<td style="width:130px;">
<p>单向绑定,</p>
<p>数据:</p>
<p>数据源->模版</p>
</td>
<td style="width:525px;">
<pre class="has">
<button [attr.aria-label]="help">help</button>
<p> </p>
</td>
</tr><tr><td>
<p>CSS 类</p>
</td>
<td style="width:125px;">
<p><code>class</code> property</p>
</td>
<td style="width:130px;">
<p>单向绑定,</p>
<p>数据:</p>
<p>数据源->模版</p>
</td>
<td style="width:525px;">
<pre class="has">
<div [class.special]="isSpecial">Special</div>
<p> </p>
</td>
</tr><tr><td>
<p>样式</p>
</td>
<td style="width:125px;">
<p><code><a href="https://www.angular.cn/api/animations/style">style</a></code> property</p>
</td>
<td style="width:130px;">
<p>单向绑定,</p>
<p>数据:</p>
<p>数据源->模版</p>
</td>
<td style="width:525px;">
<pre class="has">
<button [style.color]="isSpecial ? 'red' : 'green'">
<p> </p>
</td>
</tr></tbody></table><p> </p>
|
|