面试题答案
一键面试Angular中ngIf和ngFor指令底层原理分析
- ngIf原理:
ngIf
是一个结构型指令,用于根据表达式的值来决定是否在DOM中创建或销毁一个元素及其子树。- 当表达式为
true
时,Angular会创建一个新的视图并将其插入到DOM中。这个过程涉及到视图工厂的调用,视图工厂是一个函数,用于创建特定组件或指令的视图。 - 当表达式变为
false
时,Angular会销毁对应的视图,并从DOM中移除。这确保了不在当前状态下需要的DOM元素不会被渲染,从而提升性能。
- ngFor原理:
ngFor
也是结构型指令,用于在DOM中根据一个可迭代对象(如数组)创建多个相似的视图。- 它会遍历可迭代对象,为每个元素创建一个新的视图。对于每个视图,
ngFor
会创建一个上下文对象,包含当前迭代的索引、当前项等信息(如let i = index
,let item = current
)。 - 当可迭代对象发生变化(如数组添加或删除元素)时,
ngFor
会智能地更新DOM。它会通过跟踪每个视图的标识(通常基于对象的引用或索引),最小化DOM操作,例如只添加或删除必要的元素,而不是重新创建整个列表。
自定义ngIfOnce指令步骤和关键要点
- 步骤:
- 创建指令类:使用
@Directive
装饰器创建一个新的指令类。 - 注入必要服务:注入
TemplateRef
和ViewContainerRef
,这两个服务分别用于引用指令所在的模板和视图容器,在其中创建或销毁视图。 - 定义输入属性:定义一个输入属性来接收条件表达式的值。
- 实现逻辑:在指令类中实现逻辑,根据条件表达式的值以及是否首次为真来决定是否创建视图。
- 创建指令类:使用
- 关键要点:
- 状态跟踪:需要跟踪条件是否首次为真,这可以通过一个布尔变量来实现。
- 视图创建和销毁:正确使用
TemplateRef
和ViewContainerRef
来创建和销毁视图,确保只有在条件首次为真时创建视图。
核心代码示例
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[ngIfOnce]'
})
export class NgIfOnceDirective {
private hasRendered = false;
constructor(private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) {}
@Input() set ngIfOnce(condition: boolean) {
if (condition &&!this.hasRendered) {
this.viewContainer.createEmbeddedView(this.templateRef);
this.hasRendered = true;
} else if (!condition) {
this.viewContainer.clear();
}
}
}
在组件模板中使用该指令:
<div *ngIfOnce="someCondition">
This will be rendered only once when someCondition is first true.
</div>