水平浅,各位看官不要见怪
In Angular, the @HostBinding() function decorator allows you to set the properties of the host element from the directive class.
In Angular, the @HostListener() function decorator allows you to handle events of the host element in the directive class.
以前写前端的javascript的时候经常绑定事件,现在写angular突然不像之前那么写了,还不习惯,不过可以通过Directive和几个装饰器重新体验以前的感觉。
写一个directive实现三个功能,
- 修改innerHTMl
- 鼠标放上之后文字颜色改变,离开之后还原
- 按下鼠标,改变背景色
宿主组件的代码如下:
import {Component} from '@angular/core';
@Component({
// selector: 'app-button',
styles: [`
button {
background: blue;
color: white;
border: 1px solid #eee;
}
button.pressed {
background: aliceblue;
}
`],
template: `
<hr/>
<button appMyDirective>按下或悬停鼠标</button>
`
})
export class HostComponent {
}
1.使用directive修改innerHTML
组件从技术角度上说就是一个指令,但是由于组件对 Angular 应用来说非常独特、非常重要,因此 Angular 专门定义了 @Component 装饰器,它使用一些面向模板的特性扩展了 @Directive 装饰器。所以angular中的指令可以分为三种:结构型指令、属性(Attribute)型指令、还有就是组件。
import {Directive, HostBinding, HostListener, ElementRef, Renderer2, OnInit} from '@angular/core';
@Directive({
selector: '[appMyDirective]',
/* host: { //不用这种方式写了
'(mousedown)': 'hasPressed($event)'
}*/
})
export class ExeButtonPressDirective implements OnInit {
constructor(private el: ElementRef, private renderer: Renderer2) {
}
ngOnInit() {
this.el.nativeElement.innerHTML = '我是被指令修改过的'; // 如果放到构造函数里,会变成 '我是被指令修改过的按下或悬停鼠标'
}
}
值得说的是,我开始放到构造函数中,结果出现了问题,原因我知道了之后。
Reserve the constructor for simple initialization such as wiring constructor parameters to properties. The constructor shouldn’t do anything. It certainly shouldn’t call a function that makes HTTP requests to a remote server as a real data service would.
Constructors should do no more than set the initial local variables to simple values.
Remember also that a directive’s data-bound input properties are not set until after construction. That’s a problem if you need to initialize the directive based on those properties. They’ll have been set when ngOnInit() runs.
2.使用ElementRef和HostListener修改文字颜色
@HostListener('mouseover')
mouseOver() {
this.renderer.setStyle(this.el.nativeElement, 'color', 'red');
}
@HostListener('mouseout')
mouseOut() {
this.renderer.setStyle(this.el.nativeElement, 'color', '');
}
angular对view层做了封装和抽象,也提供了ElementRef访问视图层的元素。但是不建议使用ElementRef,因为涉及到xss攻击。
3.使用HostBinding和HostListener修改宿主元素的class实现按下鼠标改变背景色
@HostBinding('attr.role') role = 'button';
@HostBinding('class.pressed') isPressed: boolean;
另一部分代码:
// In Angular, the @HostListener() function decorator allows you to handle events of the host element in the directive class.
@HostListener('mousedown', ['$event'])
hasPressed(...arg) {
console.log(arg); // [MouseEvent]
this.isPressed = true;
}
@HostListener('mouseup') hasReleased() {
this.isPressed = false;
}
打开控制台看看发生了什么:
这是最开始的时候,不过内容已经被指令修改过了。
鼠标悬停的时候如下:
鼠标点击的时候如下:
参考文献:
https://angular.cn/guide/architecture-components#directives
https://segmentfault.com/a/1190000008878888
https://www.infragistics.com/community/blogs/b/infragistics/posts/what-are-hostbinding-and-hostlistener-in-angular