如何等待 api 中的数据加载,然后在 UI 中执行另一个操作?

How to wait for data from api to be loaded and then perform another action in the UI?

我有一个方法可以从 api 获取用户列表并填充列表组件。现在我想做什么 从 api 加载列表后,突出显示列表的第一个元素。 我已经尝试了以下方法并且它与 setTimeout 一起工作正常但是我如何在没有 setTimeout 函数的情况下实现它

这是我试过的代码,

public getUserList(){ 
    return this.http.get('https://jsonplaceholder.typicode.com/users').pipe(tap(x => {
      this.lists = x;
    }))
    .subscribe((data) => {
      setTimeout(() => { 
        this.clickFirstList();
      }, 1000);
    });
  }

clickFirstList() {
    Array.from(this.ulElement.nativeElement.children).forEach((element: HTMLElement, index: number) => {
      if (index === 0) {
        console.log(element);
        element.click();
      }
    });
}

这是 stackblitz 上的工作代码。 https://stackblitz.com/edit/angular-brpz2j?file=src/app/search-list.component.ts

我会删除 clickFirstList。并使用 css 和 angular.

我现在不知道你循环的是什么 html 元素,但可以说它是一个列表 例如:html

<ul>
  <li *ngFor="let user of list:let index = index" [class.selected]="index===selectedIndex" (click)="onClick(index)> 
    {{user.Name}}
  </li>
</ul>

和css

.selected{
   background-color: yellow;
}

在打字稿组件中:

selectedIndex = 0; //Default value. 
onClick(index:number){
   this.selectedIndex=index;
}  

Tap 还接受一个对象映射来记录下一步、错误和完成

  public getUserList(){ 
    return this.http.get('https://jsonplaceholder.typicode.com/users')
    .pipe(
       tap( {
         next: x => {
           console.log('on next', x);
         },
         error: error => {
           console.log('on error', error.message);
         },
         complete: () => {
           console.log('on complete')
           this.clickFirstList()
         }
       }))
       .subscribe((x) => {
        console.log(x)
       });
  }

你可以使用下面的代码

public getUserList(){ 
    return this.http.get('https://jsonplaceholder.typicode.com/users').pipe(tap(x => {
      this.lists = x;
    }))
    .subscribe((data) => {
    },
    (err) => {
        // code to execute if request fails
    },
    () => {
    this.clickFirstList();
    }
  });
}

你不应该那样操纵DOM,没有必要。我们使用 angular 绑定,通过使用这些绑定,我们还可以大大减少您当前拥有的代码。所以删除所有这些 DOM 操作。

首先,我们可以省略 parent 或 child 中的 lists 调用。现在你正在执行两次 get 请求,这实际上没有意义。我将 get-request 保留在 child 中。我们也可以在 OnInit 中进行请求,为什么我们需要在 AfterViewInit 中进行?

ngOnInit() {
  this.getUserList();
}

public getUserList() {
  return this.http
     // DONT USE 'ANY', type your data using interface or class
    .get<any[]>("https://jsonplaceholder.typicode.com/users")
    .subscribe(data => {
      this.lists = data;
      // you want to emit initially the first item to parent via output
      // do it here.
      this.onClickList(0, this.lists[0] || {})
    });
 }

我们还引入了一个新变量selectedIndex,我们将根据点击的项目进行更改。就像延斯在他的回答中所做的那样。您希望第一个项目最初处于活动状态,我们在上面将 0 作为索引传递给 onClick 函数:

public onClickList(i: number, item: any) {
  this.selectedIndex = i
  this.selectedList.emit(Object.assign({}, item));
}

我们像这样将其添加到模板中:

<ng-container *ngFor="let item of lists | filter: searchText; index as i">
  <li [class.active]="i === selectedIndex"
    (click)="onClickList(i, list)">
    {{ list.name }}
  </li>
</ng-container>

Your forked STACKBLITZ

如代码中的注释所述。不要使用 any,它完全违背了 TypeScript 的目的,因此请使用接口或 类 输入您的数据。我更喜欢接口。