MST
星途 面试题库

面试题:Angular中ngIf与ngFor指令底层实现原理及自定义扩展

请深入分析Angular中ngIf和ngFor指令的底层实现原理。假设现在需要基于ngIf和ngFor的原理,自定义一个类似的指令(比如ngIfOnce,只在条件首次为真时渲染元素),描述实现该自定义指令的步骤和关键要点,并给出核心代码示例。
46.2万 热度难度
前端开发Angular

知识考点

AI 面试

面试题答案

一键面试

Angular中ngIf和ngFor指令底层原理分析

  1. ngIf原理
    • ngIf是一个结构型指令,用于根据表达式的值来决定是否在DOM中创建或销毁一个元素及其子树。
    • 当表达式为true时,Angular会创建一个新的视图并将其插入到DOM中。这个过程涉及到视图工厂的调用,视图工厂是一个函数,用于创建特定组件或指令的视图。
    • 当表达式变为false时,Angular会销毁对应的视图,并从DOM中移除。这确保了不在当前状态下需要的DOM元素不会被渲染,从而提升性能。
  2. ngFor原理
    • ngFor也是结构型指令,用于在DOM中根据一个可迭代对象(如数组)创建多个相似的视图。
    • 它会遍历可迭代对象,为每个元素创建一个新的视图。对于每个视图,ngFor会创建一个上下文对象,包含当前迭代的索引、当前项等信息(如let i = indexlet item = current)。
    • 当可迭代对象发生变化(如数组添加或删除元素)时,ngFor会智能地更新DOM。它会通过跟踪每个视图的标识(通常基于对象的引用或索引),最小化DOM操作,例如只添加或删除必要的元素,而不是重新创建整个列表。

自定义ngIfOnce指令步骤和关键要点

  1. 步骤
    • 创建指令类:使用@Directive装饰器创建一个新的指令类。
    • 注入必要服务:注入TemplateRefViewContainerRef,这两个服务分别用于引用指令所在的模板和视图容器,在其中创建或销毁视图。
    • 定义输入属性:定义一个输入属性来接收条件表达式的值。
    • 实现逻辑:在指令类中实现逻辑,根据条件表达式的值以及是否首次为真来决定是否创建视图。
  2. 关键要点
    • 状态跟踪:需要跟踪条件是否首次为真,这可以通过一个布尔变量来实现。
    • 视图创建和销毁:正确使用TemplateRefViewContainerRef来创建和销毁视图,确保只有在条件首次为真时创建视图。

核心代码示例

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>