我们通过使用 @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>