我们通过使用 @Directive 装饰器来创建自定义指令。
基本结构:
import { Directive } from '@angular/core';
@Directive({
selector: '[appToolTip]'
})
export class ToolTipDirective {
constructor() { }
}
注意:selector: ‘[appToolTip]’ 里的 appToolTip 是一个属性选择器,它是用来将指令与HTML元素进行匹配。
构造函数
constructor() { }
中,通常会注入两个比较重要的依赖:ElementRef 与 Renderer。
其中,ElementRef 是实际 DOM 元素的包装器,我们可以通过 nativeElement 属性访问实际 DOM 元素。
Renderer 是渲染器,由于 Angular 是跨平台构建应用(Web、移动 Web、移动应用、原生应用和桌面原生应用等),因此 Angular 提供了一套独立于各类平台,用于操作元素的方法。
引入两种依赖:
import { Directive, ElementRef, Renderer2 } from '@angular/core';
@Directive({
selector: '[appToolTip]'
})
export class ToolTipDirective {
constructor(
private el: ElementRef,
private renderer: Renderer2,
) { }
}
接下来,我们创建一个自定义的指令 appToolTip,当鼠标移动到该元素的时候,appToolTip 显示,当鼠标移出该元素的时候,appToolTip 隐藏。
例子:
toolTip.directive.ts
import { Directive, ElementRef, Renderer2, Input, HostListener } from '@angular/core';
@Directive({
selector: '[appToolTip]'
})
export class ToolTipDirective {
// Input 装饰器,用来标记输入属性
@Input() content!: string;
toolTip: any;
constructor(
private el: ElementRef,
private renderer: Renderer2,
) { }
// HostListener 装饰器,用于声明要监听的 DOM 事件,并提供在该事件发生时要运行的处理器方法。
@HostListener('mouseenter', ['$event'])
onMouseEnter(event: any) {
if (!this.toolTip) { this.open(); }
}
@HostListener('mouseleave')
onMouseLeave() {
if (this.toolTip) { this.close(); }
}
open(){
this.toolTip = this.renderer.createElement('span');
const text = this.renderer.createText(this.content);
this.renderer.appendChild(this.toolTip, text);
this.renderer.appendChild(document.body, this.toolTip);
let hostPos = this.el.nativeElement.getBoundingClientRect();
//let tooltipPos= this.toolTip.getBoundingClientRect();
let top = hostPos.bottom + 10 ;
let left = hostPos.left;
//this.renderer.addClass(this.toolTip, 'tooltip');
this.renderer.setStyle(this.toolTip, 'position', 'absolute');
this.renderer.setStyle(this.toolTip, 'background', 'red');
this.renderer.setStyle(this.toolTip, 'top', `${top}px`);
this.renderer.setStyle(this.toolTip, 'left', `${left}px`);
}
close(){
this.renderer.removeClass(this.toolTip, 'tooltip');
this.renderer.removeChild(document.body, this.toolTip);
this.toolTip = null;
}
}
如果需要使用该指令,需要在 Module 中引入指令:
in-payment.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ReactiveFormsModule } from '@angular/forms';
import { InPaymentRouteModule, Components } from './in-payment.routing.module';
import { MaterialModule } from '@common/material/material.module';
import { InPaymentService } from './service/in-payment.service';
import { PassPaginatorModule } from '@common/material/pass-paginator/pass-paginator.module';
// 引入指令
import { ToolTipDirective } from '@common/service/directive/toolTip.directive';
@NgModule({
declarations: [
...Components,
// 注入指令
ToolTipDirective,
],
imports: [
CommonModule,
ReactiveFormsModule,
InPaymentRouteModule,
MaterialModule,
PassPaginatorModule,
],
providers: [
InPaymentService
],
})
export class InPaymentModule { }
最后,在该 Module 管辖的模板文件中,就可以使用指令:
in-payment.component.html
<span appToolTip content="国内案件">国内案件</span>