3.揭秘angular2学习 ------- 模版

模版

  1. 模版是一种自定义的标准化页面,通过模版和模版中的数据结合,可以生成各种各样的网页。
  2. 几乎所有HTML语法在模版中都是适用的,除了script标签。另外html body base等元素并不起什么作用。

模版语法概览

实例名称说明语法
<p>{{ detail.telNum }}</p>插值绑定值到模版中{{ 模版表达式 }}
<div [title]="name">test</div>DOM元素属性绑定将模版表达式name的值绑定到div元素的title属性上[DOM元素属性]=”模版表达式” 或 bind-DOM元素属性=”模版表达式”
<td [attr.colspan]="{{ 1+2 }}>test</td>HTML标签特性绑定将模版表达式的返回值绑定到元素<td>标签特性colspan上[attr.html标签特性]=”模版表达式”
<div [class.isbule]="true"></div>Class类绑定当模版表达式为true时为div添加类名为isblue的样式[class.css类名]=”模版表达式”(只是影响样式,还是直接影响元素是否有这个类?)
<div [style.color]="red"></div>Style样式绑定模版表达式的值赋值给样式的属性[style.css样式属性名]=”模版表达式”
<a (click)="edit($event)"></a>事件绑定模版语句是一个事件调用(事件)=”模版语句” 或者 on-事件=”模版语句”
div [(title)]="name"></div>双向绑定组件和模版件双向数据绑定[(绑定目标)]=”模版表达式” 或者 bindon-绑定目标=”模版表达式”
<input type="text" ##name name="name" id="name" /><p>{{ name.value }}</P>模版局部变量在当前模版中创建一个对id值为name的input元素的引用变量name,相当于getElementById(‘name’)变量名 或者 ref-变量名
<p>今天是{{today丨date}}管道操作符通过管道将数据格式化展示输入数据丨管道名:管道参数
<p>{{ detail?.telNum }}模版表达式操作符模版表达式操作符表明detail.telNum属性不是必须存在的,如果它是undefined,那么后面的表达式将会被忽略,不会引发异常?.
<P *myUnless="boolValue"></p>星号前缀使用星号前缀可简化对结构指令的使用,Angular会将带有星号的指令引用替换成带有<template>标签的代码*指令

数据绑定

概述

Angular提供了一种简单的机制,可以从模版里取值与赋值,使得数据读写更加方便。
数据绑定根据流向可分为以下三种:
1. 单向绑定:从数据源到视图目标(属性绑定):[]
2. 单向绑定:从视图目标到数据源(事件绑定):()
3. 双向绑定:数据源至视图是[ ],视图至数据源是(),所以双向绑定就是他们的结合[( )]。

除了插值之外,都有’=’,左边成为绑定目标,右边成为绑定源。

重要
区分DOM对象属性(Property)与HTML标签特性(Attribute)。
1. DOM对象属性(Property):以DOM元素作为对象,其附加的内容,实在文档对象模型里定义的,如childNodes、firstChild等。
2. HTML标签特性(Attribute):是DOM节点自带的属性,是在HTML里定义的,即只要是HTML标签中出现的属性(HTML)代码都是Attribute,如href,type等。

区别和联系
1. 大多数情况下,DOM对象属性与HTML标签特性并不是一一对应的,但少量属性即使DOM对象属性,又是HTML标签特性。如id,title,class等。
2. 通常HTML标签特性代表着初始值,而初始化后就不再发生变化。而DOM对象属性代表着当前的值,默认为初始值,但会变化。

这里自己理解一下:HTML特性首先是存在文档中,然后通过文档形成DOM对象。HTML特性是在初始化形成DOM时发挥作用,然后值就一直不变了。而DOM对象属性其实是程序运行的基本内容。而某些HTML特性同时又是DOM对象属性。比如id和class,我们再写HTML文档的时候会经常写上这两个属性。在形成网页后,我们又可以在控制台获取某个DOM对象的id、class属性值。但是HTML特性在初始化后就不再变化,但DOM对象属性是可读可写的。

Angular数据绑定是借助于元素和指令的DOM对象属性和事件来运作的,而不是HTML标签特性。

插值

  1. 数据绑定最常见的就是插值,用双大括号将模版表达式包围起来。{{ contact.tel }}
  2. Angular会先计算模版表达式中的值,然后再将结果展示出来。

模版表达式

  1. 模版表达式类似于JavaScript表达式,绝大部分的JavaScript表达式都是合法的模版表达式(听起来有点耳熟,HTML?模版。。)
  2. 模版表达式应用在插值语法的双大括号中和属性绑定”=”的右侧引号中。Angualr会执行这个表达式,并将值分配给一个绑定目标的属性。
  3. 不可以使用以下可能引发副作用的JavaScript表达式:
    • 带有new运算符的表达式
    • 赋值表达式(=、+=、-=)
    • 带有 ; 或者 , 的链式表达式
    • 带有自增和自减操作符的表达式
  4. 其他与JavaScript语法不同且值得注意的特性包括
    • 不支持位运算符( | 和 & )
    • 部分模版表达式操作符被赋予了新的意义,如管道操作符( | )和安全导航操作符( ?. )等

模版表达式的上下文

  1. 模板表达式的上下文通常就是它所在组件的实例,可以包含组件外的对象,比如模版局部变量。
  2. 模版表达式不能引用任何全局命名空间中的成员,如window、document等。也不能调用console.log()或Math.random()方法。

模版表达式的书写原则

  1. 避免视图变化的副作用:
    • 模版表达式只能改变目标属性的值,不应改变引用的任何状态。Angular的单向数据流模式正式基于这条原则而来。
  2. 能够高效地执行
    • Angular执行表达式的频率特别高,计算成本较大时慎重使用。
  3. 使用简单的语句
  4. 幂等性优先
    • 幂等的表达式总是会返回完全一致的东西,避免副作用。

属性绑定

插值和属性绑定只能设置DOM元素属性,不能设置HTML标签特性


DOM元素属性绑定

<div [title]="titleText">hello world</div>

DOM对象属性title就是绑定目标,也可以选择bind-前缀的形式来实现,这种方式又成为标准形式。

<div bind-title="titleText"hello world</div>

下面例子是用来设置Angular指令的属性:

<div [ngStyle]="styles">xxx</div>

此外还可以使用属性绑定设置自定义标签的输入属性(这是父子组件间通讯的重要途径)

<user-detail [user]="currentUser"></user-detail>

中括号

属性绑定中中括号到底什么作用?先看下面两行代码

<div [title]="titleText">hello world</div>
<div title="titleText">hello world</div>

中括号的作用是执行=右侧的模版表达式,然后将执行结果赋值给DOM的title属性。
没有中括号则直接将双引号内的内容当作文本赋值给title属性。

HTML标签特性绑定

在赋值给标签特性时,直接使用数据绑定会报错。需要使用[attr.attribute]的形式。

CSS类绑定

CSS即使DOM属性,同时又事HTML标签特性,所以以下方法均可以使用:

<div class="font"></div>

<div class="red" [class]="tessssssst"></div>

<div [class.red]="true"></div>

注意
在第二个例子中,当使用DOM对象属性绑定 给 [class]绑定值时,tessssssst对象会重写这个div元素的全部class。
在第三个例子中,根据模版表达式的boolean型结果,决定是否将red属性绑定在标签上。

style样式绑定

[style.style-name.单位]=”模版表达式”
样式属性名可以使用烤肉串命名法background-color,也可以使用驼峰命名法backgroundColor。

属性绑定与插值的关系

属性绑定和插值都能实现数据绑定。看下面两个例子

<div>{{userName}}</div>

<div [innerText]="userName"></div>

在渲染视图之前,Angualr会将插值表达式转换为属性绑定的形式,它只是属性绑定的语法糖。

事件绑定

(目标事件)=”模版语句”
on-目标事件=”模版语句”

模版语句

模版语句与模版表达式一样,与JavaScript的表达式类似,但两者的解析器是不同的,模板语句除了支持”=”赋值操作外,也支持用分号或者逗号串联起多条语句。

与模版表达式相同的是,有一些JavaScript表达式在模版语句中是不被支持的:
1. 赋值操作,+=、-=
2. 自增和自减
3. new操作符
4. 位运算符、|、&
5. 模版表达式运算符

模版表达式与模版语句一样,只能访问其上下文环境的成员,模版语句的上下文环境就是绑定事件对应组件的实例。模版语句的上下文也可以包含组件之外的对象,如模版局部变量和事件绑定语句中的$event。

目标事件可以是自定义事件,Angular在解析目标事件时,会优先判断是否匹配已知指令的事件。

自定义事件

借助EventEmitter可以创建自定义事件。

  1. 创建一个EventEmitter实例对象,并将其以输出属性的形式暴露出来。
  2. 父组件通过绑定这个输出属性来自定义一个事件,在组件中调用EventEmitter.emit(payload)来触发自定义事件。其中playload可以传入任何值,父组件绑定的事件可以通过$event对象来访问playload。

数据双向绑定

数据双向绑定就是组件-模版、模版-视图的数据双向流动。如果用之前学过的知识来写数据双向绑定

<input [value]="currentUser.name" (input)="currentUser.name=$event.target.value/>"

将两者结合起来

<input [ngModule]="currentUser.name" (ngModuleChange)="currentUser.name="$event"/>

觉得上面写发还是麻烦,再来看下面

<input [(ngModule)]="currentUser.name" />

前缀形式

<input bindon-ngModule="currentUser.name" />

[( )]这种方式只能设置一个数据绑定属性,若想设置多个,就得采用展开形式写,也就是第二段代码。

输入和输出属性

前面已经学习过输入(@Input)和输出(@Output)属性了,这里就不写例子了,记录一下前面没学到的东西
1. 如果在组件元数据中使用了inputs、outputs,那么在该组件中就不能再使用@Input、@Output了
2. 给输入、输出属性定义别名
- 方式1:@Input(别名)事件属性名=…
- 方式2:outputs:[‘组件属性名 : 别名’]

内置指令

Angular提供了指令来扩展元素的功能,下面来学习Angular提供的内置指令。

NgClass

  1. 可以同时添加或移除多个类。
  2. [ngClass]=”{类名 : value对象}”,value对象是一个布尔类型的值,当值为true时添加对应的类名到模版元素中,反之则移除。
  3. 另外一种用法:
<div [ngClass]="setClasses()"></div>
setClasses(){
    let classes = {
        red : this.red,
        font14 : !this.font14,
        title : this.isTitle
    }
}

[ngClass]=”{className1 : true , className2 : false …}”

NgStyle

  1. 在前面学过的属性绑定中,Style样式绑定只能绑定单个样式。而使用ngStyle我们可以绑定多个样式。
  2. [ngStyle]=”{‘color’ : ‘ref’, ‘font-size’ : ‘16px’, …}”
  3. 使用方式与前面ngClass类似

NgIf

  1. NgIf指令绑定一个布尔类型的表达式,当表达式值为true时,在DOM节点上添加一个元素及其子元素,反之移除
<div *ngIf="collect.length=== 0"></div>

NgSwitch

  1. NgSwitch指令需要结合NgSwitchCase和NgSwitchDefault指令来使用,根据NgSwitch绑定的模版表达式的返回值来决定添加哪个模版元素到DOM节点上,并移除其他备选模版元素
  2. 这三个相互合作的指令分别表示:
    • ngSwitch:绑定到一个返回控制条件的值的表达式
    • ngSwitchCase:绑定到一个返回匹配条件的值的表达式
    • ngSwidchDefault:用于标记默认元素的属性
  3. 注意不要在ngSwitch前使用*,而应该使用属性绑定。另外在ngSwitchCase和ngSwitchDefault的前面加上*
<span [ngSwitch]="contactName">
    <span *ngSwitchCase="first">第一</span>
    <span *ngSwitchCase="second">第二</span>
    <span *ngSwitchDefault>无名次</span>
</span>

NgFor

  1. NgFor指令可以实现重复执行某些步骤来展示数据。
<li *ngFor="let contactItem of contactList">
    <list-li [contact]="contactItem" (routerNavigate)="aaaaaa($event)"></list-li>
</li<
  1. NgFor指令支持一个可选的index索引。
<div *ngFor="let contact of contacts; let i=index">{{ i+1 }} - {{ contact.id }}</div>

NgForTrackBy

在一些包含复杂列表的项目中,每次更改会引发很多相互关联的DOM操作,使NgFor的性能变得很差。
按书中通讯录例子来说,当重新从服务器拉取列表数据,拉去到的数据可能包含很多之前显示过的数据。虽然这些数据中的联系人编号并没有发生变化,但Angular并不知道哪些列表数据在数据更新前已经渲染过。只能清理旧列表的DOM元素,然后用新的列表重新填充DOM建立一个列表。

这种情况下,可以通过追踪函数来避免这种重复渲染的性能浪费。追踪函数可以让Angular将具有相同Id的对象处理成同一个联系人:

trackByContact(index:number, contact: Contact){
    return contact.id;
}

然后通过NgForTrackBy指令设置追踪函数

<div *ngFor="let contact if contacts; trackBy: trackByContacts">{{ contact.id }}</div>

如果检查出同一个联系人的属性发生了变化,Angualr就会更新元素,反之则会留下这个元素。
使用NgForTrackBy指令的最终效果就是让列表界面变得更加顺畅,响应更及时。

版权说明

本博客内所有揭秘angular2学习的文章都是学习《揭秘Angular2》—广发证券互联网金融技术团队著作这本书的学习总结及部分内容摘抄,若有侵权请与本人联系删除侵权内容。
qq:451354
邮箱:451354@qq.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值