一、数据绑定
1、根据数据流方向可以分为三种:
单向:从数据源到视图:
//插值DOM元素属性 <p>{{ detail.telNo}}</P> //绑定HTML标签特性 <div [title]="sex"></div> //绑定--属性绑定 <div [style.color]="color">hello world</div>
单向:从视图到数据源:
//事件绑定 (click)="showDetail()" on-click="showDetail()"
双项:
//双向绑定 <div [(title)]="subject"></div> <div bindon-title="subject"></div>
数据绑定是借助于DOM对象属性和事件来运作的。
2、属性绑定
DOM元素属性绑定:把DOM对象属性绑定到组件的属性上,而绑定目标可以是中括号,也可以加前缀,还可以使用属性绑定设置自定义组件的输入属性。
//中括号 --HTML标签div的属性title <div [title]="titleText"></div> //加前缀 <div bind-title="titleText"></div> //自定义组件的输入属性 <user-detail [user]="curUser"></user-detail> //table 的属性colspan, 注意attr <table> <tr> <td [attr.colspan]="{{ 1 + 2 }}"></td> </tr> </table>
3、Css绑定:CSS类既属于DOM对象属性,也属于HTML标签特性,所以可以使用以上两种方式绑定:
<div class='red font14' [class]="changeGreen">14号 绿色字</div> //特有的绑定方式:[class.class-name]语法,被赋值为true时,将class-name这个类添加到该绑定的标签上,否则移除这个类。 <div [class.class-blue]="isBlue()">若isBlue()返回true,这里的字体将变成蓝色</div> <div class="footer" [class.footer]="showFooter">若showFooter为false,则footer这个css被移除</div> //Style样式绑定:HTML标签内联样式可以通过Style样式绑定的方式设置。语法为[style.style-property],可以带单位如px和% <button [style.background-color]="canClick ? 'green' : 'red'">若canClick为true,则按钮背景颜色为green</button> <button [style.font-size.px]="isLarge ? 19 : 3">若isLarge为true,则按钮字体变为18px</button>
二、自定义事件的绑定
借助EventEmitter
实现。它的实现步骤:一、在组件中创建EventEmitter
实例对象,并将其以输出属性形式暴露;二、父组件通过绑定一个属性来自定义一个事件;三、在组件中调用EventEmitter.emit()
触发自定义事件;四、父组件绑定的事件通过$event
对象访问数据。
//父组件collection.component.ts import { Component } from '@angular/core'; @Component({ selector: 'collection', template: `<contact-collect [contact]="detail" (onCollect)="collectMoney($event)"></contact-collect>` }) export class CollectionComponent implements OnInit{ detail: any = {}; collectMoney(){ this.detail.collection == 0 ? this.detail.collection = 1 : this.detail.collection = 0; } } //子组件contactCollect.component.ts import { Component } from '@angular/core'; @Component({ selector: 'contact-collect', template: `<i [ngClass]="{collected: contact.collection}" (click)="collectMoney()">收藏</i>` }) export class CollectionComponent implements OnInit{ @Input() contact: any = {}; @Output() onCollect = new EventEmitter<boolean>(); collectMoney(){ this.onCollect.emit(); } }
子组件click
事件触发collectMoney()方法,该方法调用EventEmitter
实例化对象onCollect()
的emit
方法,向父组件发送数据;父组件绑定了子组件的onCollect
事件,该事件被触发后将调用父元素的collectMoney($event)
方法,并以$event
访问数据。
三、内置命令
1、ngClass:通过它,可以动态添加或移除多个类。NgClass
绑定一个由CSS
类名:value
的对象,value是一个布尔类型的数据值,当value
为true
时添加对应的类名到模板元素中,反之删除。
setClasses(){ let classes={ red: this.red, font13: !this.font13, title: this.isTitle } return classes } <div [ngClass]="setClass()"></div>
2、NgStyle:设置多个内联样式。绑定刑如CSS
属性名:value
的对象。
setStyles(){ let styles = { 'color': this.red ? 'red' : 'blue', 'font-size': !this.font13 ? '13px' : '19px', 'font-weight': this.isSpecial ? 'bold' : 'normal' }; return styles; } <div [ngStyle]="setStyles"></div>
3、NgIf:绑定一个布尔类型的表达式,当表达式真时候,DOM树节点上添加一个元素及其子元素,否则移除(查看DOM树不能看到该元素)。
<ion-col size="6">
<span class="gray_font_color">数量:</span>
<span *ngIf="cargo.quantity">{{cargo.quantity}}{{cargo.quantityUnit}}</span>
<span *ngIf="!cargo.quantity">无</span>
</ion-col>
4、NgSwitch:根据NgSwitch
绑定的模板表达式返回值决定添加那个模板元素到DOM节点上。
<ion-col size="1" [ngSwitch]="adrsType"> <div *ngSwitchCase="addressTypeEnmus.PICKUP_POINT" class="pick-unld-point bg-green">装</div> <div *ngSwitchCase="addressTypeEnmus.UNLOADING_POINT" class="pick-unld-point bg-red">卸</div> </ion-col>
5、NgFor:重复执行某些步骤来展现数据,它支持一个可选的index索引,下标范围为0<=index<数组的长度。
<div *ngFor="let pickAdrs of commPickAdrslist;let i=index" id="{{pickAdrs.commonlyAddressUuid}}"> <app-order-address [adrs] = "pickAdrs" [adrsIndex]="i" [adrsType]="addressTypeEnmus.PICKUP_POINT" (onDelAdrs)="delAdrs($event)" (onGainAdrs)="gainAdrs($event)" (onAddAdrs)="addAdrs($event)" (onEditAdrs)="editAdrs($event)"></app-order-address> </div>
6、NgForTrackBy:每次更改都会引发很多相关联的DOM操作,使用NgFor
会让性能变得很差,比如重新从服务器拉取列表数据,虽然大部分数据没变化,但是因为不知道哪些数据变化了,需要清空并重新渲染。可以通过使用追踪函数避免重复渲染的性能浪费。【待深入研究】
trackByContacts(index: number, contact: Contact){ return contact.id; } <div *ngFor="let contact of contacts; trackBy: trackByContacts">{{ contact.id }}</div>
四、管道
1 、什么是管道
Angular中,管道可以按照开发者指定的规则将模板内的数据进行转换。
模板中,通过管道操作符 | 使用管道,| 左边的为输入数 据,右边为管道。管道可以带有参数,通过传入参数输出不同格式数据。同时,模板表达式中可以同时使用多个管道进行不同的处理。
2 、几种管道
1)内置管道:Angular提供的,不需导入可以直接使用。
- DatePipe:日期管道,格式化日期,纯管道
- JsonPipe:将输入数据对象经过JSON.stringify()方法转换后输出对象字符串,非纯管道
- UpperCasePipe:文本中所有小写字母全转换为字母,纯
- LowerCasePipe:变成小写,纯
- DecimalPipe:将数值按特定格式显示文本,纯
- CurrencyPipe:数值转化为本地货币格式,纯
- PercentPipe:数值转百分比,纯
- SlicePipe:将数值或者字符串裁剪成新的子集,非纯管道
expression | date: format expression | json expression | uppercase expression | lowercase expression | number[: digitInfo] 例如:保留三位小数 <span *ngIf="cargo.weight">{{cargo.weight | number : '1.0-3'}}{{weightUnit[cargo.weightUnit]}}</span> expression | currency[: currencyCode[: symbolDisplay[: digitInfo]]] expression | percent expression | slice: start[: end]
2)自定义管道
- 定义元数据:引入Pipe和PipeTransform,同时为管道命名
//sexreform.pipe.ts import { Pipe, PipeTransform } from "@angular/core"; @Pipe { name: 'sexReform' } export class SexReform implements PipeTransform { //... }
- 实现transform方法
export class SexReform implements PipeTransform { transform(val: string): string { switch(val) { case 'male': return '男'; case 'female' return '女'; default: return '未知性别'; } } }
- 使用自定义管道
//使用管道前,需要在@NgModule的元数据declarations数组中添加自定义管道 import { SexReform } from 'pipes/sexreform.pipe'; @NgModule ({ //... declarations: [SexReform] }) //可以像内置管道一般使用自定义管道咯 @Component ({ selector: 'pipe-demo-custom', template: ` <p>{{ sexValue | sexReform }}</p> ` })
纯管道与非纯管道的区别:只有发生纯变才会调用该管道,这类管道称为纯管道,其余的管道成为非纯管道。纯变指的是对基本数据类型(String、Number、Boolean)输入值的变更或者对对象引用(Array、Function、Object)的更改。
只要数据发生改变,均会触发非纯管道,但不一定会触发纯管道,需要考察数据变化的情形是否为纯变化。看下面这个例子:
@Component ({ selector: 'pure-pipe-demo', template: ` <div> <p>{{ dateObj | date: "y-MM-dd HH:mm:ss EEEE" }}</p> <p>{{ dateStr | date: "y-MM-dd HH:mm:ss EEEE" }}</p> </div> ` }) export class PurePipeDemoComponent { dateObj: date = new Date('2020-06-09 19:19:09'); dateStr: string = '2020-06-09 19:19:09'; constructor(){ setTimeout(() => { this.dateObj.setMonth(11), this.dateStr = '2020-12-03 03:03:03' },3000); } }
初始日期分别为:
2020-06-09 19:19:09 Friday
2020-06-09 19:19:09 Friday
3S后变成:
2020-06-09 19:19:09 Friday
2020-12-03 03:03:03 Thursday