3.5 指令与服务
Angular的指令(Directive)组件与过滤器(Filter)组件的主要使用场景都是在HTML页面视图里。这两种组件与其他Angular组件一样,都是在代码模块Module内定义,只不过它们的实例可以通过Angular框架在解析HTML页面视图时自动创建。因为它们都对作用域对象在页面展现有影响,本节将介绍它们的一些基本知识。
3.5.1 指令是什么
在3.3.2节,我们已经提前接触体验过Angular框架内置的指令了。Angular建立了一套完整、可扩展、用来帮助Web应用开发的指令集机制,它使得HTML可以转变成“特定领域语言(DSL)”,是用来扩展浏览器能力的技术之一。在DOM编译期间,和HTML关联着的指令会被Angular框架的编译器检测到,并且被调用执行。这种机制使得指令可以为DOM指定扩展行为,或者改变HTML原有组件的默认行为。
指令的实质是“当关联的HTML结构进入编译阶段时应该执行的操作”,它只是一个当编译器编译到相关DOM时需要执行的函数,可以被写在HTML元素的名称、属性、CSS类名和注释里(后两种形式的指令出现和应用较稀少)。
Angular通过称为指令属性来扩展的HTML控件属性,其属性名称带有前缀ng,它的实质是绑定在DOM元素上的函数。在该函数内部可以操作DOM、调用方法、定义行为、绑定控制器等。当浏览器启动、开始解析HTML时,DOM元素上的指令属性就会跟其他属性一样被解析,也就是说当一个Angular应用启动,Angular编译器就会遍历DOM树来解析HTML,寻找这些指令属性函数,在一个DOM元素上找到一个或多个这样的指令属性函数,它们就会被收集起来、排序,然后按照优先级顺序被执行。Angular应用的动态性和响应能力,都要归功于指令属性。比较常见的有:ngIf、ngFor,此外其他的如ngClass、ngStyle、ngSwitch等多个指令。本书将在它们第一次出现的位置结合示例代码解释其作用。
3.5.2 指令的使用
指令是Angular框架里最复杂的组件种类,没有之一。因为指令是Angular里被唯一能操作DOM的组件,并且构成了图3.1中数据模型与视图交流互动的桥梁。出于复用和定制的目的,做Angular应用开发将不可避免要碰到定义自己的指令的需要。
【ngFor】像for循环一样,可以重复的从数组中取值并显示出来。
// .ts
this.userInfo = ['张三', '李四', '王五'];
// .html
<div class="ui list" *ngFor="let username of userInfo"> <div class="item">{{username}}</div> </div>
他的语法是*ngFor="let username of userInfo",其中userInfo是从中取值的数组,username是每次从中取出来的值。然后在这个标签里面的内容就会重复执行,并通过双向绑定,将username显示出来。
【ngIf】根据条件决定是否显示或隐藏这个元素。
// .html <div *ngIf="false"></div> <div *ngIf="a > b"></div> <div *ngIf="username == '张三'"></div> <div *ngIf="myFunction()"></div>
(1)永远不会显示。
(2)当a大于b的时候显示。
(3)当username等于张三的时候显示。
(4)根据myFunction()这个函数的返回值,决定是否显示。
【ngSwitch】防止条件复杂的情况导致过多地使用ngIf。
// .html
<div class="container" [ngSwitch]="myAge"> <div *ngSwitchCase="'10'">age = 10</div> <div *ngSwitchCase="'20'">age = 20</div> <div *ngSwitchDefault="'18'">age = 18</div> </div>
[ngSwitch]先与目标进行绑定,ngSwitchCase列出每个可能性,ngSwitchDefault列出默认值。
【ngStyle】可以使用动态值给特定的DOM元素设定CSS属性。
// .ts backColor: string = 'red';
// .html <div [style.color]="yellow"> 你好,世界 </div> <div [style.background-color]="backColor"> 你好,世界 </div> <div [style.font-size.px]="20"> 你好,世界 </div> <div [ngStyle]="{color: 'white', 'background-color': 'blue', 'font-size.px': '20'}"> 你好,世界 </div>
(1)直接设置颜色为yellow。
(2)设置背景颜色为backColor,并可以在.ts文件中对backColor的值进行修改。
(3)设置字体大小,需要注意的是只写font-size会报错,必须在后面加上.px;当然.em.%都是可以的。
(4)前三种都是只设置一个,写[ngStyle]可以同时设置多个,使用花括号包住里面的内功。需要注意的是连字符-是不允许出现在对象的键名当中的,如果使用background-color等时需要加上单引号。
【ngClass】动态地设置和改变一个给定DOM元素的CSS类。
// .scss .bordered { border: 1px dashed black; background-color: #eee; }
// .ts isBordered: boolean = true;
// .html <div [ngClass]="{bordered: isBordered}"> 是否显示边框 </div>
scss中设置了样式,相当于你建了一个class="bordered",ts中新建了一个isBordered,用于判断是否显示.scss中的样式。html中用isBordered作为bordered是否显示的判断依据。
【ngNonBindable】告诉Angular不要绑定页面的某个部分。
.html
<divngNonBindable> {{我不会被绑定}} </div>
使用了ngNonBindable,花括号就会被当作字符串一起显示出来。