5.2 Custom Directives
5.2 Custom Directives
需求: 为元素设置默认背景颜色, 鼠标移入时的背景颜色以及移出时的背景颜色.
ng g d directives/hover
import { AfterViewInit, Directive, ElementRef } from '@angular/core';
import { After } from 'v8';
// @Directive是个装饰器, 用来告诉Angular这是一个指令
@Directive({
selector: '[appHover]'
})
export class HoverDirective implements AfterViewInit {
constructor(private elementRef: ElementRef) {
//elementRef是一个指向宿主元素的引用
//ElementRef是一个包装器,它包装了一个原生的DOM元素,可以通过nativeElement属性访问它
// console.log(elementRef);
}
ngAfterViewInit(){
console.log(this.elementRef.nativeElement);
}
}
import { AfterViewInit, Directive, ElementRef } from '@angular/core';
import { After } from 'v8';
// @Directive是个装饰器, 用来告诉Angular这是一个指令
@Directive({
selector: '[appHover]'
})
export class HoverDirective implements AfterViewInit {
element: Element
constructor(private elementRef: ElementRef) {
//elementRef是一个指向宿主元素的引用
//ElementRef是一个包装器,它包装了一个原生的DOM元素,可以通过nativeElement属性访问它
// console.log(elementRef);
this.element = elementRef.nativeElement;
}
ngAfterViewInit(){
console.log(this.element);
}
}
import { AfterViewInit, Directive, ElementRef } from '@angular/core';
import { After } from 'v8';
// @Directive是个装饰器, 用来告诉Angular这是一个指令
@Directive({
selector: '[appHover]'
})
export class HoverDirective implements AfterViewInit {
element: HTMLElement
constructor(private elementRef: ElementRef) {
//elementRef是一个指向宿主元素的引用
//ElementRef是一个包装器,它包装了一个原生的DOM元素,可以通过nativeElement属性访问它
// console.log(elementRef);
this.element = elementRef.nativeElement;
}
ngAfterViewInit(){
this.element.style.backgroundColor = 'red';
}
}
hover.directive.ts
import { AfterViewInit, Directive, ElementRef, Input } from '@angular/core';
import { After } from 'v8';
interface Options{
bgColor?: string; // ? 表示可选
}
// @Directive是个装饰器, 用来告诉Angular这是一个指令
@Directive({
selector: '[appHover]'
})
export class HoverDirective implements AfterViewInit {
@Input("appHover") appHover: Options = {}
// @Input 是一个装饰器,用来告诉Angular这个属性是一个输入属性
// Options是一个接口,用来定义输入属性的类型
element: HTMLElement
constructor(private elementRef: ElementRef) {
//elementRef是一个指向宿主元素的引用
//ElementRef是一个包装器,它包装了一个原生的DOM元素,可以通过nativeElement属性访问它
// console.log(elementRef);
this.element = elementRef.nativeElement;
}
ngAfterViewInit(){
this.element.style.backgroundColor = this.appHover.bgColor||'skyblue';
}
}
<!-- <div [appHover]="{bgColor: 'red' }">Hello Angular </div> -->
<div [appHover]="{}">Hello Angular </div>
hover.directive.ts
:
import { AfterViewInit, Directive, ElementRef, HostListener, Input } from '@angular/core';
import { After } from 'v8';
interface Options{
bgColor?: string; // ? 表示可选
}
// @Directive是个装饰器, 用来告诉Angular这是一个指令
@Directive({
selector: '[appHover]'
})
export class HoverDirective implements AfterViewInit {
@Input("appHover") appHover: Options = {}
// @Input 是一个装饰器,用来告诉Angular这个属性是一个输入属性
// Options是一个接口,用来定义输入属性的类型
element: HTMLElement
constructor(private elementRef: ElementRef) {
//elementRef是一个指向宿主元素的引用
//ElementRef是一个包装器,它包装了一个原生的DOM元素,可以通过nativeElement属性访问它
// console.log(elementRef);
this.element = elementRef.nativeElement;
}// 可以通过ElementRef指令拿到元素
ngAfterViewInit(){
this.element.style.backgroundColor = this.appHover.bgColor||'skyblue';
}
// 组件初始化完成后,才能获取到元素
@HostListener('mouseenter') enter(){
this.element.style.backgroundColor = "pink";
}
@HostListener('mouseleave') leave(){
this.element.style.backgroundColor = 'blue'
}
}
在 Angular 中,自定义指令是扩展和增强 DOM 元素行为的重要工具。你提到的
@Directive
装饰器和相关的概念(如@Input
、ElementRef
等)是创建和使用自定义指令的核心部分。以下是它们的含义及作用的详细解释。自定义指令分类
Angular 提供两种类型的指令:
- 结构型指令(Structural Directive) - 改变 DOM 的结构,例如
*ngIf
和*ngFor
。 - 用于动态添加、移除或替换元素。- 属性型指令(Attribute Directive) - 改变元素的外观或行为,例如
ngClass
和ngStyle
。 - 不改变 DOM 结构,仅修改属性或样式。创建自定义指令的关键工具
1.
@Directive
装饰器
@Directive
是定义自定义指令的装饰器。- 用法类似
@Component
,但它不包含模板或样式。示例:
import { Directive, ElementRef, Renderer2 } from '@angular/core'; @Directive({ selector: '[appHighlight]' // 使用时加 [] 表示属性型指令 }) export class HighlightDirective { constructor(private el: ElementRef, private renderer: Renderer2) { this.renderer.setStyle(this.el.nativeElement, 'backgroundColor', 'yellow'); } }
- 作用:为目标元素添加黄色背景色。
- 使用:
2.
@Input
@Input
是一个装饰器,用于从父组件向指令传递值。- 通常结合 setter 使用,可以拦截并基于传入的值执行操作。
示例:
@Directive({ selector: '[appHighlight]' }) export class HighlightDirective { @Input() set appHighlight(color: string) { this.renderer.setStyle(this.el.nativeElement, 'backgroundColor', color || 'yellow'); } constructor(private el: ElementRef, private renderer: Renderer2) {} }
- 作用:允许动态设置背景颜色。
- 使用:
3.
ElementRef
ElementRef
是 Angular 提供的类,用于直接访问 DOM 元素。- 属性
nativeElement
包含该 DOM 元素的引用。注意:直接使用
ElementRef
操作 DOM 存在安全风险(如 XSS 攻击)。通常建议搭配Renderer2
使用。示例:
4.
Renderer2
Renderer2
是一种安全操作 DOM 的抽象层。- 它提供的方法可以安全地修改 DOM,而不用直接访问
nativeElement
。示例:
constructor(private el: ElementRef, private renderer: Renderer2) { this.renderer.setStyle(this.el.nativeElement, 'color', 'blue'); // 安全地设置样式 }
5.
ViewContainerRef
和TemplateRef
这些主要用于结构型指令,帮助动态操作 DOM 结构。
TemplateRef
:表示一个嵌套模板,用于动态生成视图。ViewContainerRef
:表示视图容器,可以向其中添加或移除视图。示例:创建一个自定义的
*appIf
指令import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core'; @Directive({ selector: '[appIf]' }) export class AppIfDirective { @Input() set appIf(condition: boolean) { if (condition) { this.vcRef.createEmbeddedView(this.templateRef); // 添加视图 } else { this.vcRef.clear(); // 移除视图 } } constructor(private templateRef: TemplateRef<any>, private vcRef: ViewContainerRef) {} }
- 使用:
总结
工具 作用 @Directive
定义自定义指令,用于扩展 DOM 元素的行为。 @Input
从父组件传递数据到指令中,常用于动态控制指令的行为。 ElementRef
直接访问 DOM 元素。通常搭配 Renderer2
使用。Renderer2
提供安全操作 DOM 的方法,用于设置样式、属性等。 ViewContainerRef
表示视图容器,用于添加或移除动态视图,通常用于结构型指令。 TemplateRef
表示嵌套模板,配合 ViewContainerRef
使用,用于动态生成视图。