为什么在带有异步管道的 Angular 模板中未检测到 Subject.next () 发射?
Why is not Subject.next () emission detected in Angular template with async pipe?
有以下代码,我想知道为什么 Subject.next(1)
发射在模板中不可见,而 BehaviorSubject.next()
发射是可见的。
我知道将它包裹在 setTimeout()
中可以修复它,但我想了解它。
我好像 Subject.next()
是 同步的 并且 async
管道没有接收/标记为检查。
@Component({
selector: 'my-app',
template: `
<div>Subj: {{ subj$ | async }}</div>
<div>BehavSubj: {{ behavSubj$ | async }} </div>
<div>Interval: {{ interval$ | async }} </div>
`,
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
subj$ = new Subject<number>();
behavSubj$ = new BehaviorSubject<number>(1);
interval$ = interval(1000).pipe(take(100));
ngOnInit(): void {
this.subj$.next(1);
this.behavSubj$.next(2);
}
}
https://stackblitz.com/edit/angular-ivy-crnfgc?file=src/app/app.component.ts
未检测到,因为它太早了。将所有出现的 OnInit
替换为 AfterViewInit
并且有效。
import { Component, AfterViewInit, OnInit, VERSION } from "@angular/core";
import { BehaviorSubject, interval, Subject } from "rxjs";
import { take } from "rxjs/operators";
@Component({
selector: "my-app",
template: `
<div>Subj: {{ subj$ | async }}</div>
<div>BehavSubj: {{ behavSubj$ | async }}</div>
<div>Subj: {{ subj2$ | async }}</div>
<div>BehavSubj: {{ behavSubj2$ | async }}</div>
<div>Interval: {{ interval$ | async }}</div>
`,
styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit, AfterViewInit {
subj$ = new Subject<number>();
behavSubj$ = new BehaviorSubject<number>(1);
subj2$ = new Subject<number>();
behavSubj2$ = new BehaviorSubject<number>(1);
interval$ = interval(1000).pipe(take(100));
ngOnInit(): void {
this.subj$.next(1);
this.behavSubj$.next(2);
}
ngAfterViewInit(): void {
this.subj2$.next(1);
this.behavSubj2$.next(2);
}
}
首先,您必须初始化视图,以便异步管道已被订阅。然后你可以发送一个值给一个简单的主题。行为主体不同。它存储它的最后一个值。您可以先更新一个行为主题,然后订阅。这也是为什么你必须初始化一个行为主题但初始化一个基本主题没有意义的原因。
Here就是一个例子。
有以下代码,我想知道为什么 Subject.next(1)
发射在模板中不可见,而 BehaviorSubject.next()
发射是可见的。
我知道将它包裹在 setTimeout()
中可以修复它,但我想了解它。
我好像 Subject.next()
是 同步的 并且 async
管道没有接收/标记为检查。
@Component({
selector: 'my-app',
template: `
<div>Subj: {{ subj$ | async }}</div>
<div>BehavSubj: {{ behavSubj$ | async }} </div>
<div>Interval: {{ interval$ | async }} </div>
`,
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
subj$ = new Subject<number>();
behavSubj$ = new BehaviorSubject<number>(1);
interval$ = interval(1000).pipe(take(100));
ngOnInit(): void {
this.subj$.next(1);
this.behavSubj$.next(2);
}
}
https://stackblitz.com/edit/angular-ivy-crnfgc?file=src/app/app.component.ts
未检测到,因为它太早了。将所有出现的 OnInit
替换为 AfterViewInit
并且有效。
import { Component, AfterViewInit, OnInit, VERSION } from "@angular/core";
import { BehaviorSubject, interval, Subject } from "rxjs";
import { take } from "rxjs/operators";
@Component({
selector: "my-app",
template: `
<div>Subj: {{ subj$ | async }}</div>
<div>BehavSubj: {{ behavSubj$ | async }}</div>
<div>Subj: {{ subj2$ | async }}</div>
<div>BehavSubj: {{ behavSubj2$ | async }}</div>
<div>Interval: {{ interval$ | async }}</div>
`,
styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit, AfterViewInit {
subj$ = new Subject<number>();
behavSubj$ = new BehaviorSubject<number>(1);
subj2$ = new Subject<number>();
behavSubj2$ = new BehaviorSubject<number>(1);
interval$ = interval(1000).pipe(take(100));
ngOnInit(): void {
this.subj$.next(1);
this.behavSubj$.next(2);
}
ngAfterViewInit(): void {
this.subj2$.next(1);
this.behavSubj2$.next(2);
}
}
首先,您必须初始化视图,以便异步管道已被订阅。然后你可以发送一个值给一个简单的主题。行为主体不同。它存储它的最后一个值。您可以先更新一个行为主题,然后订阅。这也是为什么你必须初始化一个行为主题但初始化一个基本主题没有意义的原因。
Here就是一个例子。