You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular组件无代码变更却持续刷新问题排查求助

问题:Angular组件无代码变更却持续刷新,折叠面板无法正常使用

我正在开发个人库ngx-json-schema-viewer,用于将JSON Schema转为可视化内容。测试时遇到异常:组件无任何代码变更的情况下持续刷新,导致无法查看折叠面板后的内容。相关组件代码及Angular版本信息如下:

组件代码

import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, Input, forwardRef } from '@angular/core';

import {
  CreateEdgeComponent
} from "../../common/index";

import type { JSONSchemaNS, JSONSchema } from "../../types";

@Component({
  selector: 'jse-object-properties',
  standalone: true,
  imports: [
    CommonModule,
    forwardRef(() => CreateEdgeComponent)
  ],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <ul>
      <ng-container *ngFor="let entry of propertiesEntries">
        <jse-common-create-edge [schema]="entry[1]" [required]="isRequired(entry[0])">
          <strong name>
            {{ generatePropertyName(entry[0]) }}
          </strong>
        </jse-common-create-edge>
      </ng-container>
    </ul>
  `,
})
export class CreatePropertiesComponent {
  @Input({ required: true }) schema!: JSONSchemaNS.Object;

  get propertiesEntries() : [string, JSONSchema][] {
    return Object.entries(this.schema.properties || {});
  }

  generatePropertyName(key: string): string {
    return `${key}`;
  }

  isRequired(key: string): boolean {
    return Array.isArray(this.schema.required) ? this.schema.required.includes(key) : false;
  }
}

Angular版本信息

Angular CLI: 16.2.6
Node: 18.18.0
Package Manager: npm 9.8.1
OS: win32 x64

Angular: 16.2.9
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1602.6
@angular-devkit/build-angular   16.2.6
@angular-devkit/core            16.2.6
@angular-devkit/schematics      16.2.6
@angular/cli                    16.2.6
@angular/material               16.2.8
@schematics/angular             16.2.6
ng-packagr                      16.2.3
rxjs                            7.8.1
typescript                      5.1.6
zone.js                         0.13.3

排查方向与解决方案

1. 核心原因:Getter返回新数组触发无限变更检测循环

当前propertiesEntries是一个getter,每次调用都会通过Object.entries返回新的数组引用。在OnPush变更检测模式下,Angular会对比输入和模板绑定值的引用是否变化:

  • 每次变更检测时,模板中*ngFor绑定的propertiesEntries都会获取到新数组,Angular判定值已变更,触发组件重新渲染
  • 重新渲染又会再次调用getter生成新数组,形成无限循环,导致组件持续刷新

2. 修复方案:缓存数组引用

将propertiesEntries改为缓存值,仅在schema输入变化时更新:

export class CreatePropertiesComponent {
  private _schema!: JSONSchemaNS.Object;
  propertiesEntries: [string, JSONSchema][] = [];

  @Input({ required: true }) set schema(value: JSONSchemaNS.Object) {
    this._schema = value;
    // 仅当schema变化时才重新生成数组,保持引用稳定
    this.propertiesEntries = Object.entries(value.properties || {});
  }

  get schema(): JSONSchemaNS.Object {
    return this._schema;
  }

  generatePropertyName(key: string): string {
    return `${key}`;
  }

  isRequired(key: string): boolean {
    return Array.isArray(this._schema.required) ? this._schema.required.includes(key) : false;
  }
}

3. 额外排查点

  • 检查CreateEdgeComponent内部是否存在频繁触发变更检测的逻辑(如未清理的定时器、持续触发的订阅、输入值频繁变化等)
  • 确认父组件是否在频繁更新schema输入值,导致当前组件持续接收新的输入引用

内容的提问来源于stack exchange,提问作者jy95

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 08:40:29