【转】angular @HostListener()
原文:https://segmentfault.com/a/1190000008878888
Angular 2 HostListener & HostBinding
阅读 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 {}
以上代码运行后浏览器显示的结果:
此外,我们也可以监听宿主元素外,其它对象产生的事件,如 window
或 document
对象。具体示例如下:
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
,你就得在组件类中修改属性声明的同时修改相关的元数据。
-----------------------------------------------------------------------------------------------------
有Node.contains()原生方法的,移动端使用毫无压力。
如果不支持原生api,就写个兼容的函数,用parentNode来判断,提供一个Zepto的实现,清晰明了:
var contains = document.documentElement.contains ?
function(parent, node) {
return parent !== node && parent.contains(node)
} :
function(parent, node) {
while (node && (node = node.parentNode))
if (node === parent) return true
return false
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2018-08-17 apt安装遇到的问题
2017-08-17 With Storm Spouts, when is declareOutputFields( ) called?
2017-08-17 How to run Java main class and pass application arguments in Maven?