Angular 2 HostListener & HostBinding

32
阅读 Angular 6/RxJS 最新教程,请访问前端修仙之路

Host Element

在介绍 HostListener 和 HostBinding 属性装饰器之前,我们先来了解一下 host element (宿主元素)。

宿主元素的概念同时适用于指令和组件。对于指令来说,这个概念是相当简单的。应用指令的元素,就是宿主元素。假设我们已声明了一个 HighlightDirective 指令 (selector: '[exeHighlight]'):

<p exeHighlight>
   <span>高亮的文本</span>
</p>

上面 html 代码中,p 元素就是宿主元素。如果该指令应用于自定义组件中如:

<exe-counter exeHighlight>
    <span>高亮的文本</span>
</exe-counter>

此时 exe-counter 自定义元素,就是宿主元素。

HostListener

HostListener 是属性装饰器,用来为宿主元素添加事件监听。

HostListenerDecorator 装饰器定义

export interface HostListenerDecorator {
    (eventName: string, args?: string[]): any;
    new (eventName: string, args?: string[]): any;
}

HostListenerDecorator 装饰器应用

counting.directive.ts

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

@Directive({
    selector: 'button[counting]'
})
class CountClicks {
    numberOfClicks = 0;

    @HostListener('click', ['$event.target'])
    onClick(btn: HTMLElement) {
        console.log('button', btn, 'number of clicks:', this.numberOfClicks++);
    }
}

app.component.ts

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

@Component({
  selector: 'exe-app',
  styles: [`
    button {
      background: blue;
      color: white;
      border: 1px solid #eee;
    }
  `],
  template: `
    <button counting>增加点击次数</button>
  `
})
export class AppComponent {}

以上代码运行后浏览器显示的结果:

图片描述

此外,我们也可以监听宿主元素外,其它对象产生的事件,如 windowdocument 对象。具体示例如下:

highlight.directive.ts

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

@Directive({
    selector: '[exeHighlight]'
})
export class ExeHighlight {
    constructor(private el: ElementRef, private renderer: Renderer) { }

    @HostListener('document:click', ['$event'])
    onClick(btn: Event) {
        if (this.el.nativeElement.contains(event.target)) {
            this.highlight('yellow');
        } else {
            this.highlight(null);
        }
    }

    highlight(color: string) {
        this.renderer.setElementStyle(this.el.nativeElement, 'backgroundColor', color);
    }
}

app.component.ts

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

@Component({
  selector: 'exe-app',
  template: `
    <h4 exeHighlight>点击该区域,元素会被高亮。点击其它区域,元素会取消高亮</h4>
  `
})
export class AppComponent {}

以上代码运行后浏览器显示的结果:

图片描述

Host Event Listener

我们也可以在指令的 metadata 信息中,设定宿主元素的事件监听信息,具体示例如下:

counting.directive.ts

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

@Directive({
    selector: 'button[counting]',
    host: {
      '(click)': 'onClick($event.target)'
    }
})
export class CountClicks {
    numberOfClicks = 0;

    onClick(btn: HTMLElement) {
        console.log('button', btn, 'number of clicks:', this.numberOfClicks++);
    }
}

HostBinding

HostBinding 是属性装饰器,用来动态设置宿主元素的属性值。

HostBinding 装饰器定义

export interface HostBindingDecorator {
    (hostPropertyName?: string): any;
    new (hostPropertyName?: string): any;
}

HostBinding 装饰器应用

button-press.directive.ts

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

@Directive({
    selector: '[exeButtonPress]'
})
export class ExeButtonPress {
    @HostBinding('attr.role') role = 'button';
    @HostBinding('class.pressed') isPressed: boolean;

    @HostListener('mousedown') hasPressed() {
        this.isPressed = true;
    }
    @HostListener('mouseup') hasReleased() {
        this.isPressed = false;
    }
}

app.component.ts

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

@Component({
  selector: 'exe-app',
  styles: [`
    button {
      background: blue;
      color: white;
      border: 1px solid #eee;
    }
    button.pressed {
      background: red;
    }
  `],
  template: `
    <button exeButtonPress>按下按钮</button>
  `
})
export class AppComponent { }

以上代码运行后浏览器显示的结果:

图片描述

Host Property Bindings

我们也可以在指令的 metadata 信息中,设定宿主元素的属性绑定信息,具体示例如下:

button-press.directive.ts

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

@Directive({
    selector: '[exeButtonPress]',
    host: {
      'role': 'button',
      '[class.pressed]': 'isPressed'
    }
})
export class ExeButtonPress {
    isPressed: boolean;

    @HostListener('mousedown') hasPressed() {
        this.isPressed = true;
    }
    @HostListener('mouseup') hasReleased() {
        this.isPressed = false;
    }
}

我有话说

1.宿主元素属性和事件绑定风格指南

优先使用 @HostListener 和 @HostBinding ,而不是 @Directive 和 @Component 装饰器的 host 属性:

对于关联到 @HostBinding 的属性或关联到 @HostListener 的方法,要修改时,只需在指令类中的一个地方修改。 如果使用元数据属性 host,你就得在组件类中修改属性声明的同时修改相关的元数据。

详细信息请参考 - Angular 2 风格指南 - STYLE 06-03


如果觉得我的文章对你有用,请随意赞赏

你可能感兴趣的

semlinker 作者 · 2017年03月30日

是的,selector 用于设置匹配元素,常见的类型如下:
element-name: 元素名匹配,如 exe-app
.class: 类名匹配,如 .intro
[attribute]: 属性名匹配,如 [target]
[attribute=value]: 属性名和属性值匹配,如 [target=_blank]
:not(sub_selector): 非(sub_selector) 匹配,如 :not(p)
selector1, selector2: selector1、selector2 匹配,如 div,p

+1 回复

0

能不能加个qq好友。。。我在用这个工具。。有些不明白的

我是最帅的人 · 2017年04月03日
0

给我发私信

semlinker 作者 · 2017年04月03日
一生 · 2018年03月29日

@HostListener可以监听这些宿主元素吗?
例如: @HostListener('exe-app:keyup', ['$event'])

element-name: 元素名匹配,如 exe-app
.class: 类名匹配,如 .intro

:not(sub_selector): 非(sub_selector) 匹配,如 :not(p)
selector1, selector2: selector1、selector2 匹配,如 div,p

+1 回复

0

你好,这个问题实现了吗

小虫 · 2018年05月17日
xaclincoln · 2017年03月30日

@Directive({

selector: 'button[counting]'

}) 这里button[counting]是不是意味着这个Directive只能用于Button元素?

回复

0

是的

絡克少年 · 2017年04月06日
shenchaoran · 2017年11月22日

宿主元素对于组件来说,是指该组件还是父组件?

回复

flcwl · 2018年09月03日

作者,请问怎么配合Rxjs的debounceTime等等使用?比如监听的scroll or resize事件?

回复

载入中...