【问题标题】:Change detection with observable in Angular 7在 Angular 7 中使用 observable 进行变更检测
【发布时间】:2019-08-28 13:25:10
【问题描述】:

我有一个头像组件,它获取用户 ID 并在链接中搜索用户头像,并将其显示在 IMG 标记中

<ion-avatar [ngClass]="cssClass">
  <img
  [src]="avatar"
  onError="this.src='assets/images/profile1.jpg'" />
</ion-avatar>
 getAvatar() {
    this.userService.getAvatar(this.channelId)
      .subscribe(res => {
        this.avatar = res;
      });
  }

但是当我调用一个函数来改变用户头像时

this.userService.changeProfilePicture(picture, this.myChannelId).subscribe(...);

个人资料图片在此链接内更新,网址保持不变,但即使我销毁组件并重新加载它,它也不会在视图中更新。每次重新加载页面时,我都尝试创建一个随机时间戳并将其附加到链接中。这很好用,但在内存中多次加载相同的图像。

当我更改个人资料图片时,是否可以使用 ChangeDetection 来告诉视图更新?

getAvatar() 函数是一个发出链接的可观察对象,我不知道这是否有效

  getAvatar(channelId): Observable<string> {
    return new Observable(o => {
      o.next(`link to the avatar with the specific channel id`);
      o.complete();
    });
  }

【问题讨论】:

  • 你能创建一个 stackblitz 演示来显示问题吗?

标签: angular observable ionic4 angular-changedetection


【解决方案1】:

您是否尝试过在组件中导入更改检测器并手动检测更改?

constructor(public cd: ChangeDetectorRef) {}

 getAvatar() {
    this.userService.getAvatar(this.channelId)
      .subscribe(res => {
        this.avatar = res;
        this.cd.detectChanges();
      });
  }

【讨论】:

  • 我试过了,但什么也没发生,这个函数会在 observable 发出变化时检测变化?
  • 我在@Component装饰器changeDetection: ChangeDetectionStrategy.OnPush中使用这个属性
  • OnPush 告诉父组件只更新组件的@Input()s 以​​提高速度并尝试帮助鼓励不变性。因此,在您的情况下,运行 detectChanges 应该强制组件检查该值是否有更改。是的,在您的订阅中也是如此。只要您返回的值是一个字符串,并且该字符串与原来的不同。
  • 链接字符串保持不变,但里面的图像发生了变化
  • 啊……这就是原因。该值实际上需要更改才能更新该值。您可能需要触发刷新或其他操作,因为该值永远不会改变。
【解决方案2】:

首先你可以尝试改变

 getAvatar(channelId): Observable<string> {
    return new Observable(o => {
      o.next(`link to the avatar with the specific channel id`);
      o.complete();
    });
  }

 getAvatar(channelId): Observable<string> {
    return of('some test result')
    });
  }

为了确保您的数据管道正常(仅用于测试)。 我担心每个请求都返回new Observable 并使用o.complete(); 你实际上是在“承诺”。

从技术上讲,Angular 应该负责您的所有更改检测,但请检查您的组件是否在签名上有 changeDetection: ChangeDetectionStrategy.OnPush,这意味着 没有自动更改检测。在这种情况下,您必须使用 ChangeDetectorRef 手动触发检测。

@Component({
  selector: 'some-name',
  template: `{{count}}`,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class SomeComponent { 
  count = 0;

  constructor(private cdr: ChangeDetectorRef) {

    setTimeout(() => {
      this.count = 5;
      this.cdr.detectChanges();
    }, 1000);

  }

}

有关更多信息,请参阅 Netanel Basal 的 this awesome post

【讨论】:

  • 试试这个:onError="this.avatar='assets/images/profile1.jpg'"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-08
  • 2017-11-24
  • 1970-01-01
  • 2016-04-09
  • 1970-01-01
相关资源
最近更新 更多