Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Angular-RxJS:afterViewInit和异步管道_Javascript_Angular_Typescript_Rxjs - Fatal编程技术网

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()

如果您执行其中一项操作,它将相应地更新DOM。在您的情况下,您不使用第一个选项,因此必须使用第二个选项并在任何地方调用
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();
  }