大綱
1、宿主元素(Host Element)
2、HostListener
3、HostListenerDecorator 裝飾器應(yīng)用
4、HostBinding
5、HostBinding 裝飾器應(yīng)用
宿主元素(Host Element)
在介紹 HostListener 和 HostBinding 屬性裝飾器之前,我們先來(lái)了解一下 host element (宿主元素)。
宿主元素的概念同時(shí)適用于指令和組件。對(duì)于指令來(lái)說(shuō),這個(gè)概念是相當(dāng)簡(jiǎn)單的。應(yīng)用指令的元素,就是宿主元素。假設(shè)我們已聲明了一個(gè) HighlightDirective 指令 (selector: '[exeHighlight]'):
<p exeHighlight>
<span>高亮的文本</span>
</p>
上面 html 代碼中,p 元素就是宿主元素。如果該指令應(yīng)用于自定義組件中如:
<exe-counter exeHighlight>
<span>高亮的文本</span>
</exe-counter>
此時(shí) exe-counter 自定義元素,就是宿主元素。
HostListener
HostListener 是屬性裝飾器,用來(lái)為宿主元素添加事件監(jiān)聽。
/*
HostListenerDecorator 裝飾器定義
*/
export interface HostListenerDecorator {
(eventName: string, args?: string[]): any;
new (eventName: string, args?: string[]): any;
}
HostListenerDecorator 裝飾器應(yīng)用
/*
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>增加點(diǎn)擊次數(shù)</button>
`
})
export class AppComponent {}
/*
以上代碼運(yùn)行后瀏覽器顯示的結(jié)果:
*/

此外,我們也可以監(jiān)聽宿主元素外,其它對(duì)象產(chǎn)生的事件,如 window 或 document 對(duì)象。具體示例如下:
/*
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>點(diǎn)擊該區(qū)域,元素會(huì)被高亮。點(diǎn)擊其它區(qū)域,元素會(huì)取消高亮</h4>
`
})
export class AppComponent {}
/*
以上代碼運(yùn)行后瀏覽器顯示的結(jié)果:
*/

我們也可以在指令的 metadata 信息中,設(shè)定宿主元素的事件監(jiān)聽信息,具體示例如下:
/*
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 是屬性裝飾器,用來(lái)動(dòng)態(tài)設(shè)置宿主元素的屬性值。
/*
HostBinding 裝飾器定義
*/
export interface HostBindingDecorator {
(hostPropertyName?: string): any;
new (hostPropertyName?: string): any;
}
HostBinding 裝飾器應(yīng)用
/*
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 { }
/*
以上代碼運(yùn)行后瀏覽器顯示的結(jié)果:
*/


Host Property Bindings
我們也可以在指令的 metadata 信息中,設(shè)定宿主元素的屬性綁定信息,具體示例如下:
/*
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;
}
}
宿主元素屬性和事件綁定風(fēng)格指南
優(yōu)先使用 @HostListener 和 @HostBinding ,而不是 @Directive 和 @Component 裝飾器的 host 屬性。
對(duì)于關(guān)聯(lián)到 @HostBinding 的屬性或關(guān)聯(lián)到 @HostListener 的方法,要修改時(shí),只需在指令類中的一個(gè)地方修改。 如果使用元數(shù)據(jù)屬性 host,你就得在組件類中修改屬性聲明的同時(shí)修改相關(guān)的元數(shù)據(jù)。