Angular4 开发实战:(6) 创建指令(Directive)
button
指令:
ng g directive button
对于指令,会生成两个文件:
button.directive.ts
button.directive.spec.ts
// button.directive.ts
import { Directive } from '@angular/core';
@Directive({
selector: '[appButton]'
})
export class ButtonDirective {
constructor() { }
}
对于指令,selector
一般使用方括号属性方式,如上。<button appButton>指令按钮</button>
指令有两种:属性型指令
:修改宿主元素的样式或行为等结构型指令
,比如`*ngIf`,`*ngFor`:修改DOM结构。
button
指令还没有什么作用,下面让我们来修改一下,先往style.css
中添加下列样式:
button.btn {
padding: 10px;
background: blue;
color: #fff;
border-radius: 4px;
border: none;
}
修改button.directive.ts
:
import { Directive, ElementRef, AfterViewInit, Renderer2 } from '@angular/core';
@Directive({
selector: '[appButton]'
})
export class ButtonDirective implements AfterViewInit{
constructor(private er: ElementRef, private renderer2: Renderer2) { }
ngAfterViewInit() {
this.renderer2.addClass(this.er.nativeElement, 'btn');
}
}
在上面的代码中,我们将ElementRef
和Renderer2
注入构造函数,前者会得到添加了appButton
属性的元素,后者是Angular提供的DOM API
操作。
注:ElementRef和Renderer2后续会详解。
然后在demo-directive.component.html
中添加:
<button appButton>指令按钮/button>
当你打开网页时,会发现此button
添加上了btn样式类(背景色变蓝,字体颜色变白色)。
当然,还有一些快捷的方式来给使用了指令的宿主元素添加属性和事件:
(1) @HostBinding()
再来修改一下button.directive.ts
:
export class ButtonDirective {
@HostBinding('style.font-size') fontSize = '20px';
...
}
当你添加了上面的代码时,你会发现demo-directive.component.html
中的按钮字体变大了。
注:@HostBinding()
里是的属性和直接属性绑定是一样的效果,主要给宿主元素设置属性。
(2) @HostListener
我们还可以为宿主元素绑定事件:
// button.directive.ts
@HostListener('click') onClick() {
alert('你点了我!');
}
添加如上代码后,你可以试试点击按钮。
注:@HostListener()
里是事件名称,后面跟着一个监听函数,名称可以是任意合法的字符。
有些时候我们需要给这个指令传递一些值,如何实现呢?
还记得前面《组件通讯(@Input和@Output)》一章中我们讲过@Input()
可以设置别名。
修改button.directive.ts
:
export class ButtonDirective implements AfterViewInit {
...
@Input('appButton') name: string; // 定义别名
constructor(private er: ElementRef, private renderer2: Renderer2) { }
ngAfterViewInit() {
...
if (this.name) {
const text = this.renderer2.createText(this.name);
this.renderer2.appendChild(this.er.nativeElement, text);
}
}
}
通过@Input()
定义与指令同名的输入属性,我们就可以给指令传递参数了:// demo-directive.component.html
<button appButton="额外名称">指令按钮</button>
结构型指令
最常用的内置结构型指令有ngIf, ngFor, ngSwitch
。
(1) ngIf
在demo-directive.component.html
中添加:
<div>
<button (click)="isShow = !isShow">点击试试</button>
<div *ngIf="isShow">ngIf结构型指令</div>
</div>
随着点击按钮,isShow
属性值会在true和false之间切换,而div也会跟着显示或隐藏,其实是插入或移除。
而在Angular4中,新增else
效果(使用模板变量#name):
<button (click)="isShowElse = !isShowElse">点击试试ngIf else</button>
<div *ngIf="isShowElse else next">ngIf结构型指令中的else</div>
<ng-template #next>else效果</ng-template>
有些时候我们还可以这样:
<ng-container *ngIf="isShow"></ng-container>
ng-container
元素会将其里面的内容插入或移除,但ng-container
元素不会出现在页面里。
(2) ngFor
ngFor一般用来显示数据列表:
// demo-directive.component.html
<li *ngFor="let book of books">{{book}}</li>
// demo-directive.component.ts
this.books = ['HTML', 'Javascript'];
带索引:
<h4>带索引</h4>
<ul>
<li *ngFor="let book of books; index as i">{{i + ':' + book}}</li>
</ul>
(3) ngSwitch
ngSwitch
与JavaScript中的switch类似:
<div [ngSwitch]="animal">
<div *ngSwitchCase="'dog'">汪</div>
<div *ngSwitchCase="'cat'">喵</div>
<div *ngSwitchDefault>哼</div>
</div>
自定义结构型指令
我们可以创建自定义结构型指令my-if.directive.ts
:
import { Directive, Input, ViewContainerRef, TemplateRef } from '@angular/core';
@Directive({
selector: '[appMyIf]'
})
export class MyIfDirective {
constructor(private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef) { }
@Input() set appMyIf(condition: boolean) {
if (condition) {
this.viewContainer.createEmbeddedView(this.templateRef);
} else {
this.viewContainer.clear();
}
}
}
在上面的代码中,我们使用@Input()
属性装饰器的setter
方法来定义appMyIf
方法,里面的condition
参数就是其属性值。
使用demo-directive.component.html
:
<button (click)="isMyShow = !isMyShow">点击试试</button>
<div *appMyIf="isMyShow">自定义结构型指令appMyIf</div>
在上面的代码中,当isMyShow
变为true时,底部的内容显示出来;当为false时,底部内容消失了。
如发现任何问题或有好的建议,欢迎在下方评论留言。
更多建议: