Angular自定义指令的使用

177 阅读4分钟

本节将引导你创建“突出显示”指令,该指令会将宿主元素的背景色设置为黄色。

  1. 要创建指令,请使用 CLI 命令 ng generate directive

    ng generate directive highlight
    

    CLI 创建 src/app/highlight.directive.ts 以及相应的测试文件 src/app/highlight.directive.spec.ts,并在 AppModule 中声明此指令类。

    CLI 生成默认的 src/app/highlight.directive.ts,如下所示:

    src/app/highlight.directive.ts

    import { Directive } from '@angular/core';
    
    @Directive({
      selector: '[appHighlight]'
    })
    export class HighlightDirective {
      constructor() { }
    }
    

    @Directive() 装饰器的配置属性会指定指令的 CSS 属性选择器 [appHighlight]

  2. 从 @angular/core 导入 ElementRefElementRef 的 nativeElement 属性会提供对宿主 DOM 元素的直接访问权限。

    Import ElementRef from @angular/coreElementRef grants direct access to the host DOM element through its nativeElement property.

  3. 在指令的 constructor() 中添加 ElementRef 以注入对宿主 DOM 元素的引用,该元素就是 appHighlight 的作用目标。

  4. 向 HighlightDirective 类中添加逻辑,将背景设置为黄色。

    Add logic to the HighlightDirective class that sets the background to yellow.

    src/app/highlight.directive.ts

    import { Directive, ElementRef } from '@angular/core';
    
    @Directive({
      selector: '[appHighlight]'
    })
    export class HighlightDirective {
        constructor(private el: ElementRef) {
           this.el.nativeElement.style.backgroundColor = 'yellow';
        }
    }
    

指令支持名称空间。

src/app/app.component.avoid.html (unsupported)

<p app:Highlight>This is invalid</p>

应用属性型指令**

  1. 要使用 HighlightDirective,请将 <p> 元素添加到 HTML 模板中,并以伪指令作为属性。

    src/app/app.component.html

    <p appHighlight>Highlight me!</p>
    

Angular 会创建 HighlightDirective 类的实例,并将 <p> 元素的引用注入到该指令的构造函数中,它会将 <p> 元素的背景样式设置为黄色。

处理用户事件**

Handling user events**

本节会展示如何检测用户何时将鼠标移入或移出元素以及如何通过设置或清除突出显示颜色来进行响应。

  1. 从 '@angular/core' 导入 HostListener

    src/app/highlight.directive.ts (imports)

    import { Directive, ElementRef, HostListener } from '@angular/core';
    
  2. 添加两个事件处理程序,它们会在鼠标进入或离开时做出响应,每个事件处理程序都带有 @HostListener() 装饰器。

    Add two event handlers that respond when the mouse enters or leaves, each with the @HostListener() decorator.

    src/app/highlight.directive.ts (mouse-methods)

    @HostListener('mouseenter') onMouseEnter() {
      this.highlight('yellow');
    }
    
    @HostListener('mouseleave') onMouseLeave() {
      this.highlight('');
    }
    
    private highlight(color: string) {
      this.el.nativeElement.style.backgroundColor = color;
    }
    

要订阅本属性型指令宿主 DOM 元素上的事件(在本例中是 <p>),可以使用 @HostListener() 装饰器。

Subscribe to events of the DOM element that hosts an attribute directive, the <p> in this case, with the @HostListener() decorator.

处理程序会委托给一个辅助方法 highlight(),该方法会设置宿主 DOM 元素 el 的颜色。

The handlers delegate to a helper method, highlight(), that sets the color on the host DOM element, el.

完整的指令如下:

src/app/highlight.directive.ts

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

  constructor(private el: ElementRef) { }

  @HostListener('mouseenter') onMouseEnter() {
    this.highlight('yellow');
  }

  @HostListener('mouseleave') onMouseLeave() {
    this.highlight('');
  }

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

}

当指针悬停在 p 元素上时,背景颜色就会出现;而当指针移出时,背景颜色就会消失。

Second Highlight

将值传递给属性型指令**

本节将引导你在应用 HighlightDirective 时设置突出显示颜色。

This section walks you through setting the highlight color while applying the HighlightDirective.

  1. 在 highlight.directive.ts 中,从 @angular/core 导入 Input

    In highlight.directive.ts, import Input from @angular/core.

    src/app/highlight.directive.ts (imports)

    import { Directive, ElementRef, HostListener, Input } from '@angular/core';
    
  2. 添加一个 appHighlight 的 @Input() 属性。

    Add an appHighlight @Input() property.

    src/app/highlight.directive.ts

    @Input() appHighlight = '';
    

    @Input() 装饰器会将元数据添加到此类,以便让该指令的 appHighlight 属性可用于绑定。

  3. 在 app.component.ts,将 color 属性添加到 AppComponent

    src/app/app.component.ts (class)

    export class AppComponent {
      color = 'yellow';
    }
    
  4. 要同时应用指令和颜色,请通过 appHighlight 指令选择器使用属性绑定,将其设置为 color

    src/app/app.component.html (color)

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

    [appHighlight] 属性绑定执行两项任务:

    • 将突出显示指令应用于 <p> 元素
    • 通过属性绑定设置指令的突出显示颜色

通过用户输入来设置值**

本节指导你添加单选按钮,将你选择的颜色绑定到 appHighlight 指令。

  1. 将标记添加到 app.component.html 以选择颜色,如下所示:

    src/app/app.component.html (v2)

    <h1>My First Attribute Directive</h1>
    
    <h2>Pick a highlight color</h2>
    <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>
    
  2. 修改 AppComponent.color,使其没有初始值。

    src/app/app.component.ts (class)

    export class AppComponent {
      color = '';
    }
    
  3. 在 highlight.directive.ts 中,修改 onMouseEnter 方法,让它首先尝试使用 appHighlight 进行高亮显示,如果 appHighlight 是 undefined,则回退为 red

    src/app/highlight.directive.ts (mouse-enter)

    @HostListener('mouseenter') onMouseEnter() {
      this.highlight(this.appHighlight || 'red');
    }
    
  4. 启动本应用的开发服务器,以验证用户可以通过单选按钮选择颜色。

    Animated gif of the refactored highlight directive changing color according to the radio button the user selects

绑定到第二个属性**

本节将指导你配置应用程序,以便开发人员可以设置默认颜色。

  1. 将第二个 Input() 属性 defaultColor 添加到 HighlightDirective

    src/app/highlight.directive.ts (defaultColor)

    @Input() defaultColor = '';
    
  2. 修改指令的 onMouseEnter,使其首先尝试使用 appHighlight 进行突出显示,然后尝试 defaultColor,如果两个属性都 undefined,则变回 red

    src/app/highlight.directive.ts (mouse-enter)

    @HostListener('mouseenter') onMouseEnter() {
      this.highlight(this.appHighlight || this.defaultColor || 'red');
    }
    
  3. 若要绑定到 AppComponent.color 并回退为默认颜色“紫罗兰(violet)”,请添加以下 HTML。在这里,defaultColor 绑定没有使用方括号 [],因为它是静态的。

    src/app/app.component.html (defaultColor)

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

    与组件一样,你可以将指令的多个属性绑定添加到宿主元素上。

如果没有默认颜色(defaultColor)绑定,则默认为红色。当用户选择一种颜色时,所选的颜色将成为突出显示的颜色。

The default color is red if there is no default color binding. When the user chooses a color the selected color becomes the active highlight color.

Animated gif of final highlight directive that shows red color with no binding and violet with the default color set. When user selects color, the selection takes precedence.