[Angular2] Attribute Directive(属性指令)

Angular中的指令分为三种:

  • 组件(component):组件是有模板的指令。
  • 结构指令(structural directive):通过添加或移除DOM元素来改变DOM布局的指令。例如NgForNgIf
  • 属性指令(attribute directive):改变元素外观或行为的指令。例如内建的NgStyle

接下来我们编写一个属性指令,当鼠标悬停在元素上时改变元素的背景色。

属性指令至少需要一个Directive装饰器的控制类。Directive装饰器指定指令的选择器,控制类实现指令的行为。

构建属性指令

创建项目文件夹angular2-attribute-directives,按照QuickStart构建环境。

app文件夹下创建文件highlight.directive.ts

import {Directive, ElementRef, Input} from 'angular2/core';
@Directive({
    selector: '[myHighlight]'
})
export class HighlightDirective {
    constructor(el: ElementRef) {
       el.nativeElement.style.backgroundColor = 'yellow';
    }
}

我们从Angular库中引入了DirectiveElementRefDirective用于@Directive装饰器,ElementRef用于在指令的构造函数注入DOM元素的引用。暂时还不需要Input,但是后面会用到。

ElementRef是个能让我们直接访问DOM元素的服务,通过它的nativeElement属性。

使用属性指令

AppComponent中使用myHighlight。修改app.component.html

<h1>My First Attribute Directive</h1>
<span myHighlight>Highlight me!</span>

修改app.component.ts

import {Component} from 'angular2/core';
import {HighlightDirective} from './highlight.directive';
@Component({
  selector: 'my-app',
  templateUrl: 'app/app.component.html',
  directives: [HighlightDirective]
})
export class AppComponent { }

在浏览器中显示如下:

[Angular2] Attribute Directive(属性指令)_第1张图片

响应用户操作

接下来改成鼠标移到元素上的时候改变背景色。

我们要做的是:检测鼠标移入和移出元素的事件;响应这些事件。

在指令的元数据中添加一个host属性,在配置对象中指定鼠标事件和事件触发时调用的指令的方法。

host: {
  '(mouseenter)': 'onMouseEnter()',
  '(mouseleave)': 'onMouseLeave()'
}

host属性指向的就是应用这个指令的DOM元素。在我们这个例子中就是<span>

我们也可以用JavaScript来为DOM元素(el.nativeElement)添加事件监听。但是这样会有一些问题:在指令销毁时我们必须手动移除事件监听,而且我们需要直接使用DOM API,这是应该避免的。

接下来实现这两个事件处理器,并去掉构造函数中的内容,将注入的ElementRef改成私有变量:

constructor(private el: ElementRef) { }

onMouseEnter() { this._highlight("yellow"); }
onMouseLeave() { this._highlight(null); }

private _highlight(color: string) {
  this.el.nativeElement.style.backgroundColor = color;
}

在浏览器中显示的效果如下:

[Angular2] Attribute Directive(属性指令)_第2张图片

使用绑定配置指令

目前颜色是直接硬编码在指令中。我们应该像这样能从外部进行设置:

<p [myHighlight]="color">Highlight me!</p>

我们需要为指令扩展一个highlightColor输入属性。

export class HighlightDirective {
  @Input('myHighlight') highlightColor: string;
  private _defaultColor = 'red';
  constructor(private el: ElementRef) { }
  onMouseEnter() { this._highlight(this.highlightColor || this._defaultColor); }
  onMouseLeave() { this._highlight(null); }
  private _highlight(color:string) {
    this.el.nativeElement.style.backgroundColor = color;
  }
}

更新AppComponent的模板:

<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 [myHighlight]="color">Highlight me!</p>

PS:注意到,我们并没有为AppComponent添加color属性。Angular会自动添加。但是在实际环境中最好还是手动添加上啦。

在浏览器中的效果如下:

[Angular2] Attribute Directive(属性指令)_第3张图片

再添加一个绑定属性

我们再添加一个输入属性defaultColor

@Input() set defaultColor(colorName:string){
  this._defaultColor = colorName || this._defaultColor;
}

defaultColor属性有个setter用来覆盖默认的颜色,因此不需要getter。

我们如何绑定它呢?我们已经把myHighlight属性名称作为绑定目标了。

记住,组件也是指令。我们可以为组件添加任意多的属性绑定。就像这样:

<my-component [a]="'a'" [b]="'b'" [c]="'c'"><my-component>

同样,我们可以对属性绑定这样做:

<p [myHighlight]="color" [defaultColor]="'violet'">
  Highlight me too!
</p>

最后的效果如下:

[Angular2] Attribute Directive(属性指令)_第4张图片

完整代码

参考资料

Angular2官方文档

你可能感兴趣的:([Angular2] Attribute Directive(属性指令))