在 Angular 中有三种类型的指令:
- 组件 — 拥有模板的指令
- 结构型指令 — 通过添加和移除 DOM 元素改变 DOM 布局的指令
- 属性型指令 — 改变元素、组件或其它指令的外观和行为的指令。
组件是这三种指令中最常用的。 你在快速上手例子中第一次见到组件。
结构型指令修改视图的结构。例如,NgFor 和 NgIf。 要了解更多,参见结构型指令 guide。
属性型指令改变一个元素的外观或行为。例如,内置的 NgStyle 指令可以同时修改元素的多个样式。
创建一个简单的属性型指令
在命令行窗口下用 CLI 命令 ng generate directive
创建指令类文件。
ng g directive components3/highlight
CLI 会创建 src/app/components3/highlight.directive.ts
及相应的测试文件(src/app/components3/highlight.directive.spec.ts
),并且在根模块 AppModule
中声明这个指令类。
生成的 highlight.directive.ts
文件如下:
import { Directive } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor() { }
}
修改该文件,内容如下:
import { Directive, ElementRef } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(public el: ElementRef) {
el.nativeElement.style.backgroundColor = 'yellow';
}
}
使用属性型指令
在 home3.component.html 文件中使用定义的属性型指令。
<p appHighlight>Highlight me!</p>
实际效果如下:
响应用户引发的事件
上述案例中 appHighlight
只是简单的设置元素的颜色。接下来我们希望这个指令能够实现这么一个功能:在用户鼠标悬浮一个元素时,设置它的颜色。
修改 highlight.directive.ts
文件如下:
import { Directive, ElementRef,HostListener } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
//鼠标进入做出响应
@HostListener('mouseenter') onMouseEnter(){
this.highlight('yellow');
}
//鼠标离开做出响应
@HostListener('mouseleave') onMouseLeave() {
this.highlight(null);
}
constructor(public el: ElementRef) {
}
private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}
实际效果为:
当把鼠标移到 p
上的时候,背景色就出现了,而移开时就消失了。
使用 @Input
数据绑定向指令传递值
上述的案例只是满足了用户最简单的一个需求,但是这不够灵活,用户希望能够指定选择哪种颜色进行高亮。
此时我们的 highlight.directive.ts
文件需要另外引入 Input,如下:
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
@Input() highlightColor: string;
constructor(public el: ElementRef) {
}
// 鼠标进入做出响应
@HostListener('mouseenter') onMouseEnter() {
this.highlight(this.highlightColor || 'red');
}
// 鼠标离开做出响应
@HostListener('mouseleave') onMouseLeave() {
this.highlight(null);
}
private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}
把 home3.component.ts
改成这样:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-home3',
templateUrl: '
<h1>My First Attribute Directive</h1>
<h4>Pick a highlight color</h4>
<div>
<input type="radio" name="colors" (click)="color='lightgreen'">Green
<input type="radio" name="colors" (click)="color='yellow'">Yellow
<input type="radio" name="colors" (click)="color='cyan'">Cyan
</div>
<p appHighlight [highlightColor]="color">Highlight me!</p>
'
})
export class Home3Component implements OnInit {
color: string;
constructor() { }
ngOnInit(): void {
}
}
但是我们发现下列指令绑定变量的写法有点复杂。
<p appHighlight [highlightColor]="color">Highlight me!</p>
如果可以在应用该指令时在同一个属性中设置颜色就更好了,就像这样:
<p [appHighlight]="color">Highlight me!</p>
[appHighlight]
属性同时做了两件事:把这个高亮指令应用到了
元素上,并且通过属性绑定设置了该指令的高亮颜色。 你复用了该指令的属性选择器 [appHighlight]
来同时完成它们。 这是清爽、简约的语法。
在 @Input
的参数中把该选择器指定为别名。
@Input('appHighlight') highlightColor: string;
在指令内部,该属性叫 highlightColor
,在外部,你绑定到它地方,它叫 appHighlight
。
最终修改完毕后,页面实际效果如下:
绑定到第二个属性
上述案例的指令只有一个可定制属性,真实的应用通常需要更多。
目前,默认颜色(它在用户选取了高亮颜色之前一直有效)被硬编码为红色。应该允许模板的开发者设置默认颜色。
把第二个名叫 defaultColor
的输入属性添加到 HighlightDirective
中:
此时我们的 highlight.directive.ts
文件如下:
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
@Input('appHighlight') highlightColor: string;
@Input() defaultColor: string;
constructor(public el: ElementRef) {
}
// 鼠标进入做出响应
@HostListener('mouseenter') onMouseEnter() {
this.highlight(this.highlightColor || this.defaultColor || 'red');
}
// 鼠标离开做出响应
@HostListener('mouseleave') onMouseLeave() {
this.highlight(null);
}
private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}
把 home3.component.ts
改成这样:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-home3',
templateUrl: '
<h1>My First Attribute Directive</h1>
<h4>Pick a highlight color</h4>
<div>
<input type="radio" name="colors" (click)="color='lightgreen'">Green
<input type="radio" name="colors" (click)="color='yellow'">Yellow
<input type="radio" name="colors" (click)="color='cyan'">Cyan
</div>
<p [appHighlight]="color">Highlight me!</p>
<h4>defaultColor is violet</h4>
<p [appHighlight]="color" defaultColor="violet">Highlight me too!</p>
'
})
export class Home3Component implements OnInit {
color: string;
constructor() { }
ngOnInit(): void {
}
}
Angular 之所以知道 defaultColor
绑定属于 HighlightDirective
,是因为你已经通过 @Input
装饰器把它设置成了公共属性。
页面实际效果:
参考文献
本文作者为hresh,转载请注明。