目录
我们知道,AngularJS框架中,directive是一个重要的概念,是代码重用的基础。不过,该框架中directive的用法和配置稍显复杂。1.6版本后定义了新的component方法后,组件化编程相对更自然些。到了Angular框架中,component开始大行其道,出色的设计思想让组件化编程更为自然和易用了,而directive似乎销声匿迹了。
事实上,在Angular中,Directive的概念依然存在,Component就是一种特殊的Directive。只不过前者必须要提供视图,即Template;后者则不需要一定提供。通常情况下,非Component的Directive用于HTML标签的属性,标签可以是HTML原生的,也可以是其他Component,用途是赋予宿主标签某种行为。
本文介绍学习如何自定义一个Angular Directive。示例代码的基本结构采用了Angular官方的quickstart package,可以从官网下载。本文的示例代码可以在这里找到。
基本的Directive语法可以从官方文档找到,这里先给出总体的代码,然后依次按需解释。
import { Directive, HostBinding, HostListener, Input } from '@angular/core';
@Directive({
selector: '[craftMan]'
})
export class CraftManDirective {
private colors: string[] = [
'darksalmon', 'hotpink', 'lightskyblue', 'goldenrod', 'peachpuff',
'mediumspringgreen', 'cornflowerblue', 'blanchedalmond', 'lightslategrey'
];
@HostBinding('style.color') color: string;
@HostBinding('style.border-color') borderColor: string;
@HostBinding('class.grey-cat') isGrey = true;
@HostListener('mouseover') newColor() {
const colorIndex = Math.floor(Math.random() * this.colors.length);
this.color = this.borderColor = this.colors[colorIndex];
}
@Input() set craftMan(value) {
this.isGrey = value;
}
constructor() { }
}
我们的示例Directive的选择器为[craftMan], 在相应的HTML文件里,使用的方式如下:
<div [craftMan]="getFlag()" style="text-align:center">
<h1>
Welcome to {{ title }}!
</h1>
<img width="300" alt="Angular Logo" src=">
</div>
可以看到,这个Directive有一个输入,其值为函数getFlag的返回值。该函数的定义如下:
private seed: number = 0;
constructor() {
this.seed = Math.floor(Math.random() * 10);
}
public getFlag(): boolean {
return this.seed % 2 == 0;
}
逻辑很简单,随机生成的seed值为偶数就返回true,否则返回false。下面来详细解释每个部分。
前面说过,Directive通常附着在某个HTML标签上,用于改变这个标签(原生或自定义)的某些行为。那么其附着的标签就是它的宿主(Host)。这里的“某些行为”,可以是宿主的某些属性,比如class,style,value等等;也可以是宿主的某些事件,比如click,mouseover,input等等。前者可以用@HostBinding注解实现,后者则对应@HostListener注解。
以上面代码中第三个@HostBinding注解为例,它将isGrey变量绑定到宿主的名为grey-cat的class属性上,其含义是,当该变量为true时,就在宿主上应用grey-cat样式,否则不应用。这里isGrey有个默认值true,当然也可以在后续的逻辑中改变它,但也可以依赖其他组件的输入。比如:
@Input() set craftMan(value) {
this.isGrey = value;
}
这里使用@Input注解将传递给Directive的值设置到isGrey变量。输入的值即来自应用Directive的地方:[craftMan]=“getFlag()”。
因此,运行的结果是,每次刷新页面,宿主元素会随机显示灰色或者透明色。
再来看@HostListener注解,也比较简单。上述代码将宿主的mouseover事件,绑定到newColor函数,当鼠标已过宿主元素时,就执行该函数。我们看到,执行的结果是把color变量设置为一个随机的颜色值,这个值已经通过@HostBinding注解绑定到宿主的color style上。因此,当鼠标移过时,宿主的字体会随机改变一种颜色。
另外有几点值得一提。如果我们想访问Directive所在宿主的元素对象,可以在构造器中获得引用:
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'yellow';
}
针对@HostListener注解,有人可能会问,为什么不用DOM API直接去写事件处理函数呢?有一下三点理由:
以上就是Angular Directive的基本用法,如果需要更加深入,可以参考官方文档:
https://angular.io/guide/attribute-directives
https://angular.io/guide/structural-directives
欢迎交流讨论。