Angular的属性型指令

属性型指令能够改变一个元素、组件或其他指令的外观和行为。它和结构型指令不同,结构型指令能够添加或删除某一元素,以此改变DOM结构,也就是说,属性型指令可以改变自身,而结构型指令可以改变外界。比如说,你可以控制自己的行为,改变自己的容貌,整理自己的着装,但你无法控制自己的出生和死亡。

接下来,我们来创建一个简单的属性型指令appHighlight ,当用户把把鼠标停留在一个元素上时,改变它的背景色。
在命令行窗口用cli命令创建指令类文件,

ng generate directive highlight

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

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

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

从生成的文件中我们可以看出,属性型指令需要一个带@Directive装饰器修饰的类来支持指令需要的行为,该装饰器指定了一个用于标识属性的选择器。
@Directive装饰器中配置了该指令的属性型选择器[appHighlight],方括号表示选择器,Angular会在模板中定位每个拥有appHighlight属性的元素,并为这些元素添加本指令的逻辑。

装饰器下的类就是指令的控制器类,接下来我们要在控制器类中添加逻辑,并将其导出以便能在其它地方使用。

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

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {
    constructor(el: ElementRef) {
       el.nativeElement.style.backgroundColor = 'yellow';
    }
}

import语句从Angular的core库中导入了ElementRef类,该类用于包装某个原生元素,该类的属性nativeElement就是背后的原生元素,并且在构造函数中注入了宿主DOM元素的引用,所以我们有了直接访问宿主DOM元素的能力。

要想使用这个新的HighlightDirective,就往根组件的AppComponent 的模板中添加一个 p元素,并把该指令作为一个属性使用。

<p appHighlight>Highlight me!</p>

总结,Angular在宿主元素p上发现了一个appHighlight属性,然后它创建了一个该属性所在类HighlightDirective的实例,并将宿主元素p的引用注入到构造函数中,进行初始化,所以p元素背景色被设置成黄色。

响应用户引发的事件:

我们需要在鼠标悬浮在一个元素上时改变它的颜色,鼠标离开时复原,因此我们就要添加事件处理器。

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

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {
  constructor(private el: ElementRef) { }

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

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

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

@HostListener装饰器让你订阅宿主元素的事件,mouseenter、mouseleave是angular的内置事件,和click是一样的,表示鼠标键入和离开事件,而onMouseEnter、onMouseLeave则是自定义方法的名字,由于现在背景颜色是反复变化的,因此便不能直接在构造函数中初始化,我们单独抽取出highlight方法,让onMouseEnter、onMouseLeave方法分别去调用。

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

上述的元素颜色设置是在底层直接写死的,这样很不方便,我们希望能在外部直接设置颜色,而不需要更改底层代码。

指令类highlight.directive.ts:

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

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

  constructor(private el: ElementRef) { }

  @Input('appHighlight') highlightColor: string;

  @HostListener('mouseenter') onMouseEnter() {
    this.highlight(this.highlightColor || 'red');
  }

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

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

app.component.ts:

export class AppComponent {
  color = 'yellow';
}

app.component.html:

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

我们在指令类中引入@Input装饰器,设置输入属性highlightColor,并指定别名appHighlight,在外部设置color属性,并将color属性绑定到输入属性,以便将值传入。你也可以不设置color属性,直接把颜色赋给输入属性:appHighlight=“yellow”,但是这样不够灵活,因为如果不设置对外变量,其它指令或元素将无法与它合作。鼠标键入方法中的red目的是如果有人忘记绑定highlightColor,就将其置为红色。

绑定到第二个属性:

真实的应用中应该有多个定制属性,在本例中,我们应该设置默认属性,先尝试用highlightColor ,再用defaultColor ,如果都没设置,再用red作为后备。

@Input() defaultColor: string;

@HostListener('mouseenter') onMouseEnter() {
  this.highlight(this.highlightColor || this.defaultColor || 'red');
}

app.component.html:

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

注意,由于defaultColor属性绑定的是字符串常量,没有模板表达式需要计算,所以不需要加中括号。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值