首页 文章

具有初始值的可观察

提问于
浏览
2

使用observable,我想过滤并显示一个列表 . 仅当用户开始键入时才会触发输入 event . 因此,列表不会显示在第一位 . 在 inputEvent 开始被触发之前,如何为可观察的 this.filterLocation$ 分配默认值?

模板

<ng-template ngFor let-location [ngForOf]="filterLocation$ | async">
        <a mat-list-item href="#">{{location}}</a>
      </ng-template>

零件

ngAfterViewInit() {
const searchBox = document.querySelector('#search-input');
this.filterLocation$ = fromEvent(searchBox, 'input')
  .pipe(
    map((e: any) => {
      const value = e.target.value;
        return value ? this.locations
          .filter(l => l.toLowerCase().includes(value.toLowerCase()))
          : this.locations;
      }),
      startWith(this.locations)
  )
 }
}

使用 startWith 使列表最初显示 . 但抛出以下错误:

错误:ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后发生了变化 . 上一个值:'ngForOf:null' . 当前值:'ngForOf:name1,name2' .

live code

1 回答

  • 2

    初始值可以通过 startWith 运算符提供给observable,因为它已在现在删除的答案中提到 .

    问题是 filterLocation$filterLocation$ | async 被评估为 null 之后被分配得太迟了 . 由于更改发生在相同的刻度线上,因此会导致更改检测错误(尽管如果预期会出现 ExpressionChangedAfterItHasBeenCheckedError ,则可将其视为警告) .

    解决方案是在触发更改检测之前将代码从 ngAfterViewInit 移动到 ngOnInit .

    这并不总是可行的 . 另一种方法是异步提供一个值,因此它不会干扰初始变化检测 .

    通过使用 delay 运算符延迟整个observable(用户输入的可接受解决方案,因为它不是时间关键):

    this.filterLocation$ = fromEvent(searchBox, 'input')
      .pipe(
        map((e: any) => { 
          const value = e.target.value;
            return value ? this.locations
              .filter(l => l.toLowerCase().includes(value.toLowerCase()))
              : this.locations;
        }),
        startWith(this.locations),
        delay(0)
      )
    

    或者通过使调度程序使初始值异步:

    import { asyncScheduler } from 'rxjs'
    ...
    
      this.filterLocation$ = fromEvent(searchBox, 'input')
      .pipe(
        map((e: any) => { 
          const value = e.target.value;
            return value ? this.locations
              .filter(l => l.toLowerCase().includes(value.toLowerCase()))
              : this.locations;
        }),
        startWith(this.locations, asyncScheduler)
      )
    

相关问题