1. 自定义指令结构
- 创建指令:使用
ng generate directive
命令生成自定义指令,例如 ng generate directive myCustomDirective
。
- 导入依赖:在指令文件(
my - custom - directive.ts
)中,导入必要的模块和类型。
import { Directive, ElementRef, HostListener, Inject, OnInit, OnDestroy, Input, ChangeDetectorRef } from '@angular/core';
import { MyService } from './my - service';
- 指令类定义:
@Directive({
selector: '[appMyCustomDirective]'
})
export class MyCustomDirective implements OnInit, OnDestroy {
@Input() someInput: string;
private subscription: any;
constructor(
private el: ElementRef,
private cdRef: ChangeDetectorRef,
@Inject(MyService) private myService: MyService
) {}
- 生命周期钩子:
ngOnInit
:在指令初始化时,订阅依赖服务的数据变化。
ngOnInit() {
this.subscription = this.myService.data$.subscribe(data => {
// 根据服务数据变化执行操作
this.doSomethingWithData(data);
// 触发变更检测
this.cdRef.markForCheck();
});
}
- `ngOnDestroy`:在指令销毁时,取消订阅,防止内存泄漏。
ngOnDestroy() {
this.subscription.unsubscribe();
}
- 自定义方法:
private doSomethingWithData(data: any) {
// 例如修改指令所在元素的文本内容
this.el.nativeElement.textContent = `Data from service: ${data}`;
}
2. 依赖服务设计
- 创建服务:使用
ng generate service
命令生成服务,例如 ng generate service my - service
。
- 导入依赖:在服务文件(
my - service.ts
)中,导入 Injectable
装饰器和 Observable
相关模块。
import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject } from 'rxjs';
- 服务类定义:
@Injectable({
providedIn: 'root'
})
export class MyService {
private dataSubject = new BehaviorSubject<any>(null);
public data$ = this.dataSubject.asObservable();
updateData(newData: any) {
this.dataSubject.next(newData);
}
}
3. 变更检测策略与代码实现
- 变更检测策略选择:使用
markForCheck
方法进行精准的变更检测。在指令中,当依赖服务的数据发生变化时,调用 cdRef.markForCheck()
方法通知 Angular 检查该指令及其子组件的变化。
- 优化策略:
- 局部检测:通过
markForCheck
只触发指令及其子组件的检测,而不是整个应用的检测,从而提升性能。
- 避免不必要检测:在
doSomethingWithData
方法中,可以添加逻辑判断,只有当数据真正发生变化时才调用 markForCheck
,进一步减少不必要的检测。例如:
private lastData: any;
private doSomethingWithData(data: any) {
if (data!== this.lastData) {
// 例如修改指令所在元素的文本内容
this.el.nativeElement.textContent = `Data from service: ${data}`;
this.lastData = data;
// 触发变更检测
this.cdRef.markForCheck();
}
}