Angular提供了很多功能强大的内置指令,但在现实情况中,这些内置指令可能还不能完全满足实际要求,这时我们就需要编写自定义指令来实现特定要求。
一个属性指令需要一个控制器类,要通过@Directive装饰器把元数据附加到类上。@Directive装饰器指定了用以标记指令所关联的属性选择器,控制器类则实现了指令所对应的特定行为。
//beauty.directive.ts
import {Directive, ElementRef} from "@angular/core";
@Directive({
selector:'[beauty]'
})
export class BeautyDirective{
constructor(el:ElementRef){
el.nativeElement.style.backgroundColor='green';
}
}
在上述代码中,首先从Angular和弦模块@angular/core中引入Directive和ElementRef。Directive被用作@Directive装饰器,而ElementRef则用来访问DOM元素。接着,在@Directive装饰器中以键值对的形式定义了指令的元数据。在配置对象中,使用selector属性来标识该属性指令所关联的元素名称。
在@Directive元数据下面应该是该自定义指令的控制器类,该类实现了指令所包含的逻辑。
接下来就可以将它应用到组件中,
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { BeautyDirective} from "./directives/beauty.directive";
@NgModule({
declarations: [
AppComponent,
BeautyDirective
],
imports: [
BrowserModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
在组件中添加beauty
<h1 beauty>你好h1>
在上述自定义指令中,为元素设置的背景色是固定的,为了增加灵活性,可以在指令的外部使用绑定的方式设置背景色
import {Directive, ElementRef, Input} from "@angular/core";
@Directive({
selector:'[beauty]'
})
export class BeautyDirective{
private _defaultColor='green';
private el:HTMLElement;
@Input('beauty')
set backgroundColor(colorName:string){
this.setStyle(colorName);
};
constructor(el:ElementRef){
this.el=el.nativeElement;
this.setStyle(this._defaultColor);
}
private setStyle(color:string){
this.el.style.backgroundColor=color;
}
}
模板
<h1 [beauty]="'red'">你好h1>
在为指令绑定了输入属性后,可以根据输入值动态变更元素的样式。接下来将实现用户单击按钮时改变样式的例子。为了实现这种效果,需要在事件处理函数上添加@HostListener装饰器
@HostListener装饰器指向使用属性指令的DOM元素,使得DOM元素的事件与指令联系起来。除此之外,也可以直接为DOM元素添加事件监听器。
import {Directive, ElementRef, Input, HostListener} from "@angular/core";
@Directive({
selector:'[beauty]'
})
export class BeautyDirective{
private _defaultColor='green';
private el:HTMLElement;
@Input('beauty') backgroundColor:string;
// set backgroundColor(colorName:string){
// this.setStyle(colorName);
// };
constructor(el:ElementRef){
this.el=el.nativeElement;
this.setStyle(this._defaultColor);
}
@HostListener('click')
onClick(){
this.setStyle(this.backgroundColor||this._defaultColor);
}
private setStyle(color:string){
this.el.style.backgroundColor=color;
}
}
除了自定义属性指令外,Angular2还允许自定义结构型指令。
Unless指令需要访问组件模板内容,并且需要可以渲染组件模板的内容的工具。使用TemplateRef, ViewContainerRef服务可以实现这个目标。TemplateRef用来访问组件的模板,而ViewContainerRef可作为视图内容渲染器,将模板内容插入至DOM中。在指令构造函数中,需要将他们作为依赖注入,赋值给指令的变量,代码如下:
import {Directive, Input, TemplateRef, ViewContainerRef} from "@angular/core";
@Directive({
selector:'[myUnless]'
})
export class MyUnlessDirective{
@Input('myUnless')
set condition(newCondition:boolean){
if(!newCondition){
this.viewContainer.createEmbeddedView(this.templateRef);
console.log(newCondition);
}else {
this.viewContainer.clear();
console.log("clear");
}
}
constructor(
private templateRef:TemplateRef,
private viewContainer:ViewContainerRef
){}
}
//1
"boolValue">
false
//2
"!boolValue">
true
上述中,当boolValue的值为false,显示1,值为true,显示false