Angular之属性型指令学习

hresh 650 0

Angular之属性型指令学习

在 Angular 中有三种类型的指令:

  1. 组件 — 拥有模板的指令
  2. 结构型指令 — 通过添加和移除 DOM 元素改变 DOM 布局的指令
  3. 属性型指令 — 改变元素、组件或其它指令的外观和行为的指令。

组件是这三种指令中最常用的。 你在快速上手例子中第一次见到组件。

结构型指令修改视图的结构。例如,NgFor 和 NgIf。 要了解更多,参见结构型指令 guide。

属性型指令改变一个元素的外观或行为。例如,内置的 NgStyle 指令可以同时修改元素的多个样式。

创建一个简单的属性型指令

在命令行窗口下用 CLI 命令 ng generate directive 创建指令类文件。

ng g directive components3/highlight

CLI 会创建 src/app/components3/highlight.directive.ts 及相应的测试文件(src/app/components3/highlight.directive.spec.ts),并且在根模块 AppModule 中声明这个指令类。

生成的 highlight.directive.ts 文件如下:

import { Directive } from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {

  constructor() { }

}

修改该文件,内容如下:

import { Directive, ElementRef } from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {

  constructor(public el: ElementRef) {
    el.nativeElement.style.backgroundColor = 'yellow';
  }

}

使用属性型指令

在 home3.component.html 文件中使用定义的属性型指令。

<p appHighlight>Highlight me!</p>

实际效果如下:

Angular之属性型指令学习

响应用户引发的事件

上述案例中 appHighlight 只是简单的设置元素的颜色。接下来我们希望这个指令能够实现这么一个功能:在用户鼠标悬浮一个元素时,设置它的颜色。

修改 highlight.directive.ts 文件如下:

import { Directive, ElementRef,HostListener } from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {

  //鼠标进入做出响应
  @HostListener('mouseenter') onMouseEnter(){
    this.highlight('yellow');
  }

  //鼠标离开做出响应
  @HostListener('mouseleave') onMouseLeave() {
    this.highlight(null);
  }

  constructor(public el: ElementRef) {
  }

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

实际效果为:

Angular之属性型指令学习

当把鼠标移到 p 上的时候,背景色就出现了,而移开时就消失了。

使用 @Input 数据绑定向指令传递值

上述的案例只是满足了用户最简单的一个需求,但是这不够灵活,用户希望能够指定选择哪种颜色进行高亮。

此时我们的 highlight.directive.ts 文件需要另外引入 Input,如下:

import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {

  @Input() highlightColor: string;

  constructor(public el: ElementRef) {
  }

  // 鼠标进入做出响应
  @HostListener('mouseenter') onMouseEnter() {
    this.highlight(this.highlightColor || 'red');
  }

  // 鼠标离开做出响应
  @HostListener('mouseleave') onMouseLeave() {
    this.highlight(null);
  }

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

home3.component.ts 改成这样:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-home3',
  templateUrl: '
    <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 appHighlight [highlightColor]="color">Highlight me!</p>
  '
})
export class Home3Component implements OnInit {

  color: string;
  constructor() { }

  ngOnInit(): void {
  }

}

但是我们发现下列指令绑定变量的写法有点复杂。

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

如果可以在应用该指令时在同一个属性中设置颜色就更好了,就像这样:

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

[appHighlight] 属性同时做了两件事:把这个高亮指令应用到了

元素上,并且通过属性绑定设置了该指令的高亮颜色。 你复用了该指令的属性选择器 [appHighlight] 来同时完成它们。 这是清爽、简约的语法。

@Input 的参数中把该选择器指定为别名。

@Input('appHighlight') highlightColor: string;

在指令内部,该属性叫 highlightColor,在外部,你绑定到它地方,它叫 appHighlight

最终修改完毕后,页面实际效果如下:

Angular之属性型指令学习

绑定到第二个属性

上述案例的指令只有一个可定制属性,真实的应用通常需要更多。

目前,默认颜色(它在用户选取了高亮颜色之前一直有效)被硬编码为红色。应该允许模板的开发者设置默认颜色。

把第二个名叫 defaultColor输入属性添加到 HighlightDirective 中:

此时我们的 highlight.directive.ts 文件如下:

import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {

  @Input('appHighlight') highlightColor: string;
  @Input() defaultColor: string;

  constructor(public el: ElementRef) {
  }

  // 鼠标进入做出响应
  @HostListener('mouseenter') onMouseEnter() {
    this.highlight(this.highlightColor || this.defaultColor || 'red');
  }

  // 鼠标离开做出响应
  @HostListener('mouseleave') onMouseLeave() {
    this.highlight(null);
  }

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

home3.component.ts 改成这样:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-home3',
  templateUrl: '
    <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  [appHighlight]="color">Highlight me!</p>

    <h4>defaultColor is violet</h4>
    <p  [appHighlight]="color" defaultColor="violet">Highlight me too!</p>
  '
})
export class Home3Component implements OnInit {

  color: string;
  constructor() { }

  ngOnInit(): void {
  }

}

Angular 之所以知道 defaultColor 绑定属于 HighlightDirective,是因为你已经通过 @Input 装饰器把它设置成了公共属性。

页面实际效果:

Angular之属性型指令学习

参考文献

官方文档

发表评论 取消回复
表情 图片 链接 代码

分享