【问题标题】:Angular: handle object changes in ngFor, force printAngular:处理 ngFor 中的对象更改,强制打印
【发布时间】:2021-09-14 11:31:24
【问题描述】:

我的app.component 有一个对象列表

class Hero {
    alias: string;

    constructor(public firstName: string,
                public lastName: string) {
    }
}

class AppComponent {
...
heroes: Hero[] = [
    new Hero("foo", "bar")
];
...
onHeroChange($event: Hero, index: number): void {
    this.heroes[index] = $event;
}

<div *ngFor="let hero of heroes; let index=index">
  <hero [hero]="hero" (heroChange)="onHeroChange($event, index)"></hero>
</div>

HeroComponent

export class HeroComponent {
  @Input()
  set hero(newValue: Hero) {
    this._hero = newValue;
    this.showAlias = !!newValue.alias;
  }

  get hero(): Hero {
    return this._hero;
  }

  @Output() heroChange: EventEmitter<Hero> = new EventEmitter<Hero>();
  showAlias: boolean = !1;

  private _hero: Hero;

  //

  @HostListener('click')
  onHeroClick(): void {
    this.hero.alias = `alias_${+new Date()}`;
    console.info('HERO TO EMIT', this.hero);
    this.heroChange.emit(this.hero);
  }
}

我的问题是,即使在app.component 中分配更改后的英雄,hero.component 内的set hero 也不会被调用,因此示例中的showAlias 没有更新,我在hero.component.

我需要通过分配整个数组来强制 ngFor 吗?

也许一种解决方法是从数组中删除对象然后再次插入? 不过听起来像是无用的计算。

注意:这只是一个例子,这不是我真正在做的事情,所以像

更新 onHeroClick 方法中的 showAlias 属性

在 hero.component 中分配英雄

很遗憾没有解决问题。我需要在外部进行更改,因为会发生其他事情。

是否可以将检测更改为onPush 并手动标记以供检查?

闪电战 ==> https://stackblitz.com/edit/angular-ivy-kpn3ds

【问题讨论】:

    标签: arrays angular typescript ngfor ngonchanges


    【解决方案1】:

    您没有设置新的hero,您只是在修改现有的属性:

    this.hero.alias = `alias_${+new Date()}`;
    

    这不会触发二传手。像这样更改行:

    this.hero = {...this.hero, alias: `alias_${+new Date()}`};
    

    【讨论】:

    • 谢谢,但我提到这无法解决。更改必须从数组中反映出来,这会过早触发 hero.component 中的 setter。
    • 我可能弄错了,但在我看来你没有设置任何东西。为什么会解雇一个二传手?您在HeroComponent 上修改hero 对象,将相同的对象发送到AppComponent,这又将相同的对象再次传递给HeroComponent。没有引用改变,也没有调用 setter。为什么你会期待不同的东西?
    • 如果你查看app.component,你会看到新英雄被分配在那里。而且我不指望二传手会被解雇。我要求一个干净的解决方案,以触发 ngFor 再次打印。
    • 不是新英雄。这是对来自HeroComponent 的同一个旧(刚刚修改)英雄的引用。 ngFor 再次打印,但HeroComponent 从这个新的ngFor 循环中得到的英雄和以前一样。角度变化检测默认使用参考。为了更改 AppComponent 中的引用,您可以这样做:this.heroes[index] = {...$event};
    • 根据实际用例的复杂程度,另一种解决方案是为别名定义一个单独的组件。由于这将绑定到alias 属性(不是整个对象),因此无需将hero 视为不可变的,更改检测就可以工作:https://stackblitz.com/edit/angular-ivy-yhpv3j
    猜你喜欢
    • 2016-06-02
    • 1970-01-01
    • 2018-07-08
    • 2020-06-25
    • 2017-05-06
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多