框架
版本

概述

重要提示:此库目前处于实验阶段。这意味着在次要版本和补丁版本中都会发生重大更改。请谨慎升级。如果您在实验阶段将其用于生产环境,请将您的版本锁定到补丁级别版本,以避免意外的重大更改。

@tanstack/angular-query-experimental 包提供了一流的 API,用于通过 Angular 使用 TanStack Query。

欢迎反馈!

我们正在努力为 Angular 上的 TanStack Query 提供稳定的 API。如果您有任何反馈,请通过 TanStack Discord 服务器与我们联系,或访问 Github 上的此讨论

支持的 Angular 版本

TanStack Query 与 Angular v16 及更高版本兼容。

TanStack Query(前身为 React Query)通常被描述为 Web 应用程序缺失的数据获取库,但从更技术的角度来看,它使在 Web 应用程序中获取、缓存、同步和更新服务器状态变得轻而易举。

动机

大多数核心 Web 框架没有提供一种整体性的、有主见的数据获取或更新方式。因此,开发人员最终要么构建封装了严格数据获取意见的元框架,要么发明自己的数据获取方式。这通常意味着将基于组件的状态和副作用拼凑在一起,或者使用更通用的状态管理库来存储和提供整个应用程序中的异步数据。

虽然大多数传统的状态管理库非常适合处理客户端状态,但它们在处理异步或服务器状态方面表现不佳。这是因为服务器状态完全不同。首先,服务器状态:

  • 持久化在您可能无法控制或拥有的远程位置
  • 需要异步 API 进行获取和更新
  • 意味着共享所有权,并且可能在您不知情的情况下被其他人更改
  • 如果不小心,可能会在您的应用程序中变得“过时”

一旦您掌握了应用程序中服务器状态的本质,随着您的深入,将会出现更多挑战,例如:

  • 缓存……(可能是编程中最难的事情)
  • 将对相同数据的多个请求去重为单个请求
  • 在后台更新“过时”的数据
  • 知道数据何时“过时”
  • 尽可能快地反映数据更新
  • 性能优化,如分页和延迟加载数据
  • 管理服务器状态的内存和垃圾回收
  • 使用结构共享对查询结果进行记忆化

如果您没有被这份清单淹没,那一定意味着您已经解决了所有服务器状态问题,并且应该获得一个奖项。但是,如果您像绝大多数人一样,要么尚未解决所有或大部分这些挑战,要么我们才刚刚开始触及皮毛!

TanStack Query 无疑是管理服务器状态的_最佳_库之一。它开箱即用,无需配置,并且可以根据您的应用程序的增长进行定制,效果惊人。

TanStack Query 使您能够克服_服务器状态_的棘手挑战和障碍,并在应用程序数据开始控制您之前控制它。

从更技术的角度来看,TanStack Query 可能会:

  • 帮助您从应用程序中删除许多复杂且容易被误解的代码行,并用少量 Angular Query 逻辑取而代之。
  • 使您的应用程序更易于维护,并且更容易构建新功能,而无需担心连接新的服务器状态数据源
  • 通过使您的应用程序感觉比以往更快、响应更灵敏,从而直接影响您的最终用户。
  • 潜在地帮助您节省带宽并提高内存性能

话不多说,给我看些代码!

在下面的示例中,您可以看到 TanStack Query 以其最基本和简单的形式用于获取 TanStack Query GitHub 项目本身的 GitHub 统计信息:

在 StackBlitz 中打开

angular-ts
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { HttpClient } from '@angular/common/http'
import { CommonModule } from '@angular/common'
import { injectQuery } from '@tanstack/angular-query-experimental'
import { lastValueFrom } from 'rxjs'

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: 'simple-example',
  standalone: true,
  template: `
    @if (query.isPending()) {
      加载中...
    }
    @if (query.error()) {
      发生错误:{{ query.error().message }}
    }
    @if (query.data(); as data) {
      <h1>{{ data.name }}</h1>
      <p>{{ data.description }}</p>
      <strong>👀 {{ data.subscribers_count }}</strong>
      <strong>✨ {{ data.stargazers_count }}</strong>
      <strong>🍴 {{ data.forks_count }}</strong>
    }
  `
})
export class SimpleExampleComponent {
  http = inject(HttpClient)

  query = injectQuery(() => ({
    queryKey: ['repoData'],
    queryFn: () =>
      lastValueFrom(
        this.http.get<Response>('https://api.github.com/repos/tanstack/query'),
      ),
  }))
}

interface Response {
  name: string
  description: string
  subscribers_count: number
  stargazers_count: number
  forks_count: number
}
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { HttpClient } from '@angular/common/http'
import { CommonModule } from '@angular/common'
import { injectQuery } from '@tanstack/angular-query-experimental'
import { lastValueFrom } from 'rxjs'

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: 'simple-example',
  standalone: true,
  template: `
    @if (query.isPending()) {
      加载中...
    }
    @if (query.error()) {
      发生错误:{{ query.error().message }}
    }
    @if (query.data(); as data) {
      <h1>{{ data.name }}</h1>
      <p>{{ data.description }}</p>
      <strong>👀 {{ data.subscribers_count }}</strong>
      <strong>✨ {{ data.stargazers_count }}</strong>
      <strong>🍴 {{ data.forks_count }}</strong>
    }
  `
})
export class SimpleExampleComponent {
  http = inject(HttpClient)

  query = injectQuery(() => ({
    queryKey: ['repoData'],
    queryFn: () =>
      lastValueFrom(
        this.http.get<Response>('https://api.github.com/repos/tanstack/query'),
      ),
  }))
}

interface Response {
  name: string
  description: string
  subscribers_count: number
  stargazers_count: number
  forks_count: number
}

你说服我了,那么现在该怎么办?