在 Angular 中有三种类型的指令:
组件 — 拥有模板的指令
结构型指令 — 通过添加和移除 DOM 元素改变 DOM 布局的指令
属性型指令 — 改变元素、组件或其它指令的外观和行为的指令。
组件
组件就是拥有模板的指令,这个我们在第五节编写第一个组件中就已经牛刀小试过了。
入门的内容就那么多的,不了解的还是回去再简单的看看。
结构型指令
结构型指令就是通过添加和移除DOM元素改变DOM布局的指令,可以简单的理解为类似jq中的hide、show、append、remove等概念。
Angular里面内置了一些结构型指令。
*ngIf
类似angularjs中的ng-if,当条件成立时,添加DOM。当条件不成立时,移除DOM。
这里和angularjs中的ng-show或者ng-hide是不同的,条件不成立的时候,DOM是被移除销毁掉的。
最新的Angular没有类似简单显示或者隐藏的内置指令。
想要实现这样的功能可以动态设置class的属性就好。
用法类似:<div *ngIf="isShow">'isShow' is true</div>
*ngFor
类似angularjs中的ng-repeat,可以简单的理解为设定一个模板,然后循环一个数组的值,绑定到模板中,
最后添加到DOM上。
类似用法:this.itemList = [{value:1},{value:2}]
<div *ngFor="let item of itemList"> <a>{{item.value}}</a> </div>
以上我们写定的模板是<div><a></a></div>
,注意这里被循环添加的也是<div>
,
是从添加*ngFor
的根开始循环的。最终DOM类似<div><a>1</a></div><div><a>2</a></div>
在开发中我们比较常用到,点击事件需要传递一个参数标记,当前被点击的是哪个对象。
<div *ngFor="let item of itemList;let i = index"> <a (click)="clickItem(i)">{{item.value}}</a> </div> clickItem(index):void{ console.log(this.itemList[index]); }
在语句的后面加上;let i = index
就是讲当前的索引绑定到i对象中,就能传递到点击事件中了。
优化用法:
ngFor检测的对象是itemList整个数组。所以当数组有变化时,就好触发ngFor标签,会重新渲染整个DOM,
显然当itemList是一个大对象甚至是超大对象时,可能你只修改了,其中一个对象的一个属性,却导致了整个数组的重新渲染,显然是会导致性能降低的。
Angular提供了优化的用法。使用trackBy往组件中添加一个方法,告诉Angular它应该追踪的值。
<div *ngFor="let item of itemList;let i = index;trackBy: trackByValue"> <a (click)="clickItem(i)">{{item.value}}</a> </div> trackByValue(index: number, item:any): number { return item.value; }
ngSwitch *ngSwitchCase
效果和代码中的switch和case的组合相同,当*ngSwitchCase条件成立的时候,渲染该DOM。
类似用法:
<div *ngFor="let item of itemList;let i = index;trackBy: trackByValue"> <div [ngSwitch]="item.value" (click)="clickItem(i)"> <a *ngSwitchCase="1">value is 1:{{item.value}}</a> <a *ngSwitchCase="2">value is 2:{{item.value}}</a> </div> </div>
最终渲染DOM如:
<div _ngcontent-c2=""> <div _ngcontent-c2="" ng-reflect-ng-switch="1"> <!--bindings={"ng-reflect-ng-switch-case": "1"}--> <a _ngcontent-c2="">value is 1:1</a> <!--bindings={"ng-reflect-ng-switch-case": "2"}--> </div> </div>
属性型指令
属性型指令指的是改变元素、组件或其它指令的外观和行为的指令。
Angular中没有内置的属性型指令。
上面说了结构型指令,但是我们在开发中会比较经常用到,但是却很少会自定义结构型指令。
我们新建指令,最多的应该是组件,然后就是属性型指令了。
修改字体
我们先新建一个指令(新建指令也比较少,所以我们都放到directive目录下)
ng generate directive directive/oni-big-size
引入ElementRef
允许我们直接操作DOM。
import { Directive , ElementRef} from '@angular/core';
在项目的任意一个位置使用。
<div appOniBigSize>很大</div>
属性型指令,顾名思义就是作为标签的属性。如class、style等都是标签的属性。
添加事件
添加引用HostListener,
import { Directive , ElementRef,HostListener} from '@angular/core';
使用它装饰器添加两个事件处理器,鼠标移进,移出。
在构造函数中给el添加private属性,这个我们之前讲过了,这里是一种简写的方式。
相当于this.el =el ;这样我们就能在代码的其他地方使用el这个参数了。
然后我们设置了鼠标移进设置字体100px,移出设置字体20px。
效果:略!
给指令传参数
现在我们接着来看看怎么给属性传递参数,假设我们需要从外部传进来一个值,
作为初始值或者默认值。
这里以我们的例子来说,我们需要传进来一个默认的字体大小,当初始化和鼠标移出时我们都使用它。
添加引用Input
import { Directive,ElementRef,HostListener,Input } from '@angular/core';
Input我们会在其他的地方也经常用到它,你可以把它理解为,链接组件内和组件外的值得桥梁。
就是把组件内的一个对象绑定到组件外的对象上,这里不要求组件内和组件外的对象名称相同,
也就是说绑定允许存在别名。
使用<div appOniBigSize [initFontSize]='10'>很大</div>
同样的,我们还可以添加更多的属性。
如:<div appOniBigSize [initFontSize]='10' bigFontSize="200">很大</div>
鼠标移进效果:
移出和初始效果:
源代码:百度云 链接:http://pan.baidu.com/s/1i5FyPet 密码:w6e2
码云:https://gitee.com/xiaohuOni/oniplan-ng
有码云的帮忙给个star,感谢。
这节课的内容就到这里完成了。
感谢您的阅读。
我是莽夫,希望你开心。