繁体   English   中英

具有原始值的角按变化检测策略

[英]Angular onpush change detection strategy with primitive values

可能是我误会了angular的changeDetection策略。

这是说明:

  • 我有2个同级组件(​​S1和S2)
  • 将这两个组件都视为在其上显示一些图形数据的小部件
  • 加载后,我想最初在两个组件上显示数据。 (为此,我正在使用行为主题)
  • 我想从S1通知S2触发http服务调用。 (我使用行为主题并在S1中单击按钮时调用.next。我正在S2中订阅相同的可观察对象以获取数据)
  • 我的S2组件已向onPush更改检测策略注册。
  • 我正在使用HTTP服务进行过程中loading文本,然后在使用ngIf完成后删除文本ngIf使用原始变量this.loading=true/false

现在我的问题是,当App最初loading...时,我可以看到正在S2小部件上loading...文本,然后填充数据。

但是,当我单击S1中的“ notify sibling按钮时,它确实触发了服务调用,但是在http处理过程中,我看不到正在loading...文本。

这是S1的代码:

import { Component, OnInit } from '@angular/core';
import { MessagingService } from '../messaging.service';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {

  constructor(private _sendMessage: MessagingService) { }

  ngOnInit() {
  }
  notifyChild() {
    this._sendMessage.notifySibling();
  }
}

这是S2的代码:

import { Component, OnInit,ChangeDetectionStrategy ,ChangeDetectorRef} from '@angular/core';
import { MessagingService } from '../messaging.service';
import { switchMap, takeUntil, delay } from 'rxjs/operators';
import { of } from 'rxjs';
@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css'],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent implements OnInit {
  public loading = true;
  public myData: any;
  constructor(private _receiveMessage: MessagingService,private cd: ChangeDetectorRef) { }

  ngOnInit() {
    this._receiveMessage.registerNotification().pipe(
      switchMap(res => {
        this.loading = true;
        /** Simulate http call below  */
        return of([res.data]).pipe(
          delay(5000)
        )
      })
    ).subscribe(response => {
      this.myData = response;
      this.loading = false;
      this.cd.markForCheck();
    })
  }

}

注意:我添加了this.cd.markForCheck(); 在订阅中。 如果我像这样评论我只看到loading...而没有数据显示

讯息服务:

import { Injectable } from '@angular/core';
import { Subject, BehaviorSubject } from 'rxjs';
@Injectable({
  providedIn: 'root'
})
export class MessagingService {
  public _notify = new BehaviorSubject({ data: "initial Call" });
  public notify = this._notify.asObservable();
  constructor() { }

  notifySibling() {
    this._notify.next({ data: 'call from sibling' });
  }
  registerNotification() {
    return this.notify;
  }

}

完整的工作示例已发布在stackblitz上

仅当更改@Input属性时, OnPush策略运行检查,如果要在异步上下文中运行它,则必须在请求之前和之后this.cd.markForCheck()调用this.cd.markForCheck()

ngOnInit() {
    this._receiveMessage.registerNotification().pipe(
      switchMap(res => {
        this.loading = true;
        /** note this */
        this.cd.markForCheck();
        return of([res.data]).pipe(
          delay(1000)
        )
      })
    ).subscribe(response => {
      this.myData = response;
      this.loading = false;
      this.cd.markForCheck();
    })
  }

https://stackblitz.com/edit/angular-pmvmgz

英语不是我的母语:(

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM