概述

重要提示:此库目前处于实验阶段。这意味着次要版本和补丁版本都可能包含破坏性更改。请谨慎升级。如果在实验阶段在生产环境中使用此库,请锁定到补丁版本,以避免意外的破坏性更改。

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

欢迎反馈!

我们正在努力为 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()) {
      Loading...
    }
    @if (query.error()) {
      An error has occurred: {{ 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()) {
      Loading...
    }
    @if (query.error()) {
      An error has occurred: {{ 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
}

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