# 5.1数据绑定、响应式编程和管道

## angular提供的数据绑定：

* 插值表达式：使用插值表达式将一个表达式的值显示在模板上。示例：

  ```markup
    <h1>{{productTitle}}<hi>
  ```
* 属性绑定：使用方括号将一个表达式的值赋给Html标签的一个属性。示例：

  ```markup
    <img [src] ="imgUrl">
  ```
* 事件绑定：使用小括号将组件控制器的一个方法指定为模板中事件的处理器。示例：

  ```markup
    <button (click)="toProductDetail">商品详情</button>
  ```
* 双向绑定：使用“\[(ngModel)]”将控制器和模板关联起来，任何一方的改变都会引起另一方的改变。示例：

  ```markup
    <input [(ngModel)]="name">
  ```

## 使用插值表达式（控制器→模板DOM属性）

```markup
<h1>{{productTitle}}</h1>
<h1>{{表达式}}</h1>
```

> 注意：angular会将“插值表达式”翻译为“属性绑定” ![](https://github.com/moluo22h/notes/tree/668cd27cd99167e714ef848951046bd7205f3cef/%E7%BC%96%E7%A8%8B%E5%AD%A6%E4%B9%A0/Angular/%7B%7B...%7D%7D)等价于

## 属性绑定

### html属性和dom属性的区别

当浏览器渲染界面时，会为html标签生成一个类型为HTMLElement的Dom节点，每个dom都有自己的属性和方法。如input标签生成domInputElement

| 属性     | 描述         | 获取方式                               |
| ------ | ---------- | ---------------------------------- |
| html属性 | 不可变，其值为初始值 | event.target.value                 |
| dom属性  | 可变，其值为当前值  | event.target.getAttribute('value') |

### HTML属性和DOM属性的关系

* 少量HTML属性和DOM属性之间有着1：1的映射，如id
* 有些HTML属性没有对应的DOM属性，如colspan
* 有些DOM属性没有对应的HTML属性，如textContent
* 就算名字相同，HTML属性和DOM属性也不是同一样东西
* HTML属性的值指定了初始值，DOM属性的值表示当前值。
* HTML属性的值不能改变，DOM属性的值可以改变。
* 模板绑定使用DOM属性和事件来工作的，而不是Html属性

实战：为一个input标签设置“value”属性并添加“input”事件，“value”属性值为“初始值”，“input”事件将触发控制器的onInput()方法打印出标签的Html属性和Dom属性值

* 模板代码

  ```markup
  <input value="初始值" (input)="onInput($event)">
  ```
* 控制器代码

  ```typescript
    onInput(event: any): void {
      console.log(event);
      console.log('dom属性value值：' + event.target.value);
      console.log('html属性value值：' + event.target.getAttribute('value'));
    }
  ```

### DOM属性绑定（控制器→模板DOM属性）

angular中常使用的是DOM属性绑定。

### HTML属性绑定（控制器→模板HTML属性）

当某些标签的HTML属性没有与之对应的DOM属性时，需要使用HTML属性绑定。例如table标签colspan只有HTML属性而没有DOM属性。

* 基本Html属性绑定

  ```markup
  <td [attr.colspan]="size">...</td>
  <td [attr.HTML属性]="控制器属性">...</td>
  ```
* css类绑定

  ```markup
  <div class="xxx yyy" [class]="someExprission">...</div>
  ```

  ```markup
  <div [class.special]="isSpecial">...</div>
  <div [class.css类名]="布尔值">...</div>
  ```

  ```markup
  <div [ngClass]="{xxx:isX,yyy:isY}"></div>
  <div [ngClass]="{css类：表达式true或false}"></div>
  ```
* 样式绑定

  ```markup
  <button [style.color]="isSpecial?'red':'green' ">...</button>
  <button [style.样式属性.样式属性值单位]="判断条件?'结果为true样式属性值':'结果为false样式属性值' ">...</button>
  ```

  ```markup
  <div [ngStyle]="{'font-style':this.canSave?'italic':'normal'}">...</div>
  <div [ngStyle]="{'样式属性':判断条件?'结果为true样式属性值':'结果为false样式属性值'}">...</div>
  ```

## 事件绑定（模板→控制器）

```markup
<input (input)="onInputEvent($event)">
<input (事件名称)="控制器方法名称(浏览器事件对象)">
```

1. 事件绑定结构：

   | 结构      | 描述                |
   | ------- | ----------------- |
   | 小括号     | 表示这是个事件绑定         |
   | 事件名称    | 事件可以为：示例中为input事件 |
   | 组件方法名称  | 示例中为onInputEvent  |
   | 浏览器事件对象 | 示例中为$event        |

   > 当事件发生时执行的表达式除了上述的控制器方法，还可以为任意表达式。
2. 实战：为一个“点我”按钮添加onlick事件，事件触发时调用控制器中的onclick()方法打印出按钮的事件对象。
   * 模板代码

     ```markup
     <button (click)="onClick($event)">点我</button>
     ```
   * 控制器代码

     ```typescript
       onClick(event: object): void {
         console.log(event);
       }
     ```

## 双向绑定

双向绑定=事件绑定+属性绑定。 不过我们并不知道双向绑定中绑定的具体事件，angular将会为不同标签绑定不同的事件不同。

> 使用双向绑定时，需要在模块的@NgModule注解的imports中引入FormsModule。
