Javascript Angular-RxJS:afterViewInit和异步管道
我尝试在使用Javascript Angular-RxJS:afterViewInit和异步管道,javascript,angular,typescript,rxjs,Javascript,Angular,Typescript,Rxjs,我尝试在使用changeDetection的组件中执行以下操作:ChangeDetectionStrategy.OnPush, @ViewChild('searchInput') input: ElementRef; ngAfterViewInit() { this.searchText$ = fromEvent<any>(this.input.nativeElement, 'keyup') .pipe( map(event => even
changeDetection的组件中执行以下操作:ChangeDetectionStrategy.OnPush,
@ViewChild('searchInput') input: ElementRef;
ngAfterViewInit() {
this.searchText$ = fromEvent<any>(this.input.nativeElement, 'keyup')
.pipe(
map(event => event.target.value),
startWith(''),
debounceTime(300),
distinctUntilChanged()
);
}
如果没有任何
@Input
,async
管道正在标记我的组件以供检查,它工作正常。因此,我不明白为什么我没有得到与fromEvent
相同的行为变更检测:变更检测策略。OnPush
允许组件在更新@Input()引用时不触发变更检测。因此,如果在同一组件中执行所有操作,则不会更新@Input()引用,因此视图不会更新
我建议您使用上面的模板代码创建dumb组件,但通过@Input()为其提供searchText,并在smart组件中调用dumb组件
智能组件
模板
<div *ngIf="searchText">
results for "<b>{{searchText}}</b>"
</div>
“{searchText}}”的结果
默认情况下,每当Angular kicks执行更改检测时,它都会逐个检查所有组件,检查是否有更改,如果是,则更新其DOM。将默认更改检测更改为更改检测.OnPush
时会发生什么情况
Angular会更改其行为,并且只有两种方法可以更新组件DOM
- @输入属性引用已更改
- 手动调用markForCheck()
markForCheck()
。但有一种情况,每当您使用异步管道时,它都会为您调用此方法
异步管道订阅一个可观察或承诺,并返回
它发出的最新值。当发出新值时,异步
管道标记要检查的组件的更改。当组件
如果被销毁,异步管道将自动取消订阅以避免
潜在的内存泄漏
所以这里没有什么神奇之处,它在引擎盖下调用markForCheck()
。但如果是这样,为什么你的解决方案不起作用?为了回答这个问题,让我们深入到AsyncPipe本身。如果我们检查源代码,AsyncPipes转换函数如下所示
transform(obj: Observable<any>|Promise<any>|null|undefined): any {
if (!this._obj) {
if (obj) {
this._subscribe(obj);
}
this._latestReturnedValue = this._latestValue;
return this._latestValue;
}
....// some extra code here not interesting
}
我毫不怀疑它会起作用,但我不应该那样做。据我所知,组件内部的异步管道应该完成这项工作。这里的问题不是异步管道而是changeDetection,因为没有更新输入引用,这就是为什么changeDetection专门用于dumb组件而不是smart组件的原因。如果不想更改结构,则必须删除changeDetection onpush。在你的帖子中,使用了smart dumb组件,这个结构的角度推进我很困惑,我真的不应该这样做,异步管道应该标记组件以供检查。在没有任何输入的情况下,如果我创建一个间隔(1000)并在其上创建异步管道,我的模板将使用onpush更新。因此,你的意思是使用间隔而不是fromevent?你确定它工作吗?因为它应该是相同的,我想我将测试它。searchText$=间隔(1000)。管道(映射(()=>this.Input.nativeElement.value))。管道(startWith(“”),debounceTime(300),distinctUntilChanged());//这是正确的代码吗?我刚做了这个测试。searchText$=interval(1000)
<my-dumb-component [searchText]="searchText$ | async"></my-dumb-component>
@Input() searchText: SearchText
<div *ngIf="searchText">
results for "<b>{{searchText}}</b>"
</div>
transform(obj: Observable<any>|Promise<any>|null|undefined): any {
if (!this._obj) {
if (obj) {
this._subscribe(obj);
}
this._latestReturnedValue = this._latestValue;
return this._latestValue;
}
....// some extra code here not interesting
}
ngAfterViewInit() {
this.searchText$ =
fromEvent<any>(this.input.nativeElement, "keyup").pipe(
map((event) => event.target.value),
startWith(""),
debounceTime(300),
distinctUntilChanged()
);
this.cf.markForCheck();
}