为什么我的 Angular 子组件没有更新

问题描述 投票:0回答:1

使用 Angular 14.2,我有一个子组件,它从其父组件接收一个数组,并应该显示更新后的数组。

但事实并非如此。

如果我点击另一个页面并返回到这一页,就会显示消息,所以我知道孩子正在接收它们,只是没有显示。 我看过的所有例子都说这应该有效,所以我不确定我错过了什么。

请阅读下面的更新,问题似乎与 RxJS Subject 有某种关系

父组件:

<job-console [msgs]="consoleMessages"></job-console>
if(msg && msg.length > 0){
   console.log('msg recd: ', msg); // <-- this gets logged to console
   this.consoleMessages = [msg, ...this.consoleMessages];
   // I've also tried 'concat' and 'shift/unshift but none work
}

子组件:

<div class="console">
  <div *ngFor="let item of msgs">--{{item}}</div>
</div>
@Component({
  selector: 'job-console',
  templateUrl: './job-console.component.html',
  styleUrls: ['./job-console.component.scss']
})
export class JobConsoleComponent  {

  @Input() msgs: string[] = []
 
}

我玩过 ChangeDetectorRef(从来没有让它工作过),但这似乎应该是一个非常简单/常见的场景,无论如何都不需要达到那个程度。我也试过 ngOnChanges ,但那也行不通。这让我觉得这里发生了更大的事情。

更新

在 StackBlitz 上重新创建时,我发现问题严格来说并不是变更检测的问题。如果我只是在我的 AppComponent 中有一个

setInterval
将消息填充到
consoleMessages
中,它就可以工作。一切如期而至,不过现在想想,这可能是因为
setInterval
触发了变化检测?

无论如何,在简化我最初发布在这里的代码时,我已经删除了要显示的消息是由应用程序的另一部分通过 RxJS 主题发出的事实。因此,AppComponent 中的订阅正在接收每个发出的值(并将其记录到控制台),但是当它将它添加到 consoleMessages 时,未检测到更改。这是订阅码:

this.hub.processMessage$.subscribe( (msg: string) => {
  if(msg && msg.length > 0){
    console.log('msg recd: ', msg); // <-- this gets logged to console
      this.consoleMessages.push(msg)
    }
  })
}

我仍然有消息没有显示在 JobConsole 组件中的问题,除非我有一个

setInterval
- 它甚至不需要做任何事情。

我不确定 RxJS 是否与此有关——这似乎不太可能,但我不确定。我只需要在从主题收到消息时显示消息。

这是我在 StackBlitz 上的代码:https://stackblitz.com/edit/angular-1dtcms?file=src%2Fmain.ts。这包括 AppComponent 构造函数中的一个简单的 RxJS 间隔来发出值,并且它有效:

interval(1000).subscribe(n => {
  console.log('interval', n)
  this.consoleMessages.unshift(n.toString())
});

所以现在归结为 - 为什么 RxJS

setInterval
有效,但使用 Subject 却不行?

angular rxjs angular2-changedetection
1个回答
0
投票

让我解释一下子选择器是如何工作的。 Angular 首先加载 html,所以下面的 html 在 ts 逻辑之前加载。

<job-console [msgs]="consoleMessages"></job-console>

加载上述代码时,您可能没有为 consoleMessages 变量初始化正确的值。你所要做的就是在开始时用空数组初始化 consoleMessages 并在 html 中有一个额外的 if 检查,示例如下

<job-console [msgs]="consoleMessages" *ngIf="consoleMessages.length > 0"></job-console>

每次更新控制台消息时,再次用空数组初始化。

if(msg && msg.length > 0){
   console.log('msg recd: ', msg); // <-- this gets logged to console
   let messages = [...this.consoleMessages]; // save this data in a local variable before resting
   this.consoleMessages = [];
   this.consoleMessages = [msg, ...messages];
}

这将删除和更新 DOM,您将拥有正确的数据。我希望这能解决您的问题,如果您遇到任何问题,请告诉我。

© www.soinside.com 2019 - 2024. All rights reserved.