首页 专题 H5案例 前端导航 UI框架

Angular4 开发实战:(6) 创建指令(Directive)

作者:TG 日期: 2017-06-11 阅读: 5333
指令(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');   

  }  

}

在上面的代码中,我们将ElementRefRenderer2注入构造函数,前者会得到添加了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) ngIfdemo-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时,底部内容消失了。 如发现任何问题或有好的建议,欢迎在下方评论留言。



关注”全栈技术杂货铺“

全栈技术杂货铺