- 属性型指令:改变一个元素的外观或行为,例如NgStyle 指令可以同时修改元素的多个样式。
- 结构型指令:修改视图的结构。例如NgFor 和 NgIf等。
angular 内置了很多指令,但是这篇笔记主要记录如何自定义指令。
创建指令
- 导入 Directive 装饰器(而不再是 Component), 指令带有 @Directive 装饰器。
- 导入所需符号 Input、TemplateRef 和 ViewContainerRef, 任何结构型指令都会用到以上三个(属性型常用:ElementRef、HostListener)。
- 给指令类添加装饰器。
- 设置 CSS 属性选择器 ,以便在模板中标识出这个指令该应用于哪个元素。
// 创建指令的 CLI 命令ng generate directive highlight复制代码
import { Directive } from '@angular/core';@Directive({ // 定义一个 CSS 属性型选择器 [appHighlight], 通常带前缀(除ng),如app等,确保它们不会与标准 HTML 属性冲突 selector: '[appHighlight]'})export class HighlightDirective { constructor() { }}复制代码
属性型指令
import { Directive, ElementRef, HostListener, Input } from '@angular/core';@Directive({ // [appHighlight]定义了一个CSS 属性选择器 // 属性名应该拼写成小驼峰形式,并且带有一个前缀,如app。这个前缀不能用 ng,因为它只属于 Angular 本身。 selector: '[appHighlight]'})export class HighlightDirective { // ElementRef 通过其 nativeElement 属性可以直接访问宿主 DOM 元素 constructor(private el: ElementRef) { } // @Input 的参数中把该选择器highlightColor指定为别名appHighlight。 @Input('appHighlight') highlightColor: string; // @HostListener 装饰器订阅某个属性型指令所在的宿主 DOM 元素的事件 @HostListener('mouseenter') onMouseEnter() { this.highlight(this.highlightColor || 'red'); } @HostListener('mouseleave') onMouseLeave() { this.highlight(null); } private highlight(color: string) { this.el.nativeElement.style.backgroundColor = color; }}复制代码
Highlighted in orange
复制代码
结构型指令
结构型指令中星号()被放在指令的属性名之前, Angular 会把星号()语法解开成
<ng-template>
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';@Directive({ selector: '[appUnless]'})export class UnlessDirective { private hasView = false; // 使用TemplateRef取得的内容,并通过ViewContainerRef来访问这个视图容器 constructor( private templateRef: TemplateRef , private viewContainer: ViewContainerRef) { } // 没有人会读取 appUnless 属性,因此它不需要定义 getter。 @Input() set appUnless(condition: boolean) { if (!condition && !this.hasView) { this.viewContainer.createEmbeddedView(this.templateRef); this.hasView = true; } else if (condition && this.hasView) { this.viewContainer.clear(); this.hasView = false; } }}复制代码
1111
复制代码