查询是对异步数据源的声明式依赖,它与一个唯一的键绑定。查询可以与任何基于 Promise 的方法(包括 GET 和 POST 方法)一起使用,以从服务器获取数据。如果你的方法修改了服务器上的数据,我们建议使用 突变 代替。
要在你的组件或服务中订阅查询,请调用 injectQuery,至少需要
import { injectQuery } from '@tanstack/angular-query-experimental'
export class TodosComponent {
info = injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodoList }))
}
import { injectQuery } from '@tanstack/angular-query-experimental'
export class TodosComponent {
info = injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodoList }))
}
你提供的唯一键在内部用于重新获取、缓存以及在你的应用程序中共享你的查询。
由 injectQuery 返回的查询结果包含了关于查询的所有信息,你将需要在模板和任何其他数据使用场景中使用这些信息
result = injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodoList }))
result = injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodoList }))
result 对象包含了一些非常重要的状态,你需要了解这些状态才能高效工作。一个查询在任何给定时刻只能处于以下状态之一
除了这些主要状态之外,根据查询的状态,还可以获得更多信息
对于大多数查询,通常只需检查 isPending 状态,然后是 isError 状态,最后,假设数据可用并渲染成功状态
@Component({
selector: 'todos',
standalone: true,
template: `
@if (todos.isPending()) {
<span>Loading...</span>
} @else if (todos.isError()) {
<span>Error: {{ todos.error()?.message }}</span>
} @else {
<!-- We can assume by this point that status === 'success' -->
@for (todo of todos.data(); track todo.id) {
<li>{{ todo.title }}</li>
} @empty {
<li>No todos found</li>
}
}
`,
})
export class PostsComponent {
todos = injectQuery(() => ({
queryKey: ['todos'],
queryFn: fetchTodoList,
}))
}
@Component({
selector: 'todos',
standalone: true,
template: `
@if (todos.isPending()) {
<span>Loading...</span>
} @else if (todos.isError()) {
<span>Error: {{ todos.error()?.message }}</span>
} @else {
<!-- We can assume by this point that status === 'success' -->
@for (todo of todos.data(); track todo.id) {
<li>{{ todo.title }}</li>
} @empty {
<li>No todos found</li>
}
}
`,
})
export class PostsComponent {
todos = injectQuery(() => ({
queryKey: ['todos'],
queryFn: fetchTodoList,
}))
}
如果布尔值不是你喜欢的,你也可以使用 status 状态
@Component({
selector: 'todos',
standalone: true,
template: `
@switch (todos.status()) {
@case ('pending') {
<span>Loading...</span>
}
@case ('error') {
<span>Error: {{ todos.error()?.message }}</span>
}
<!-- also status === 'success', but "else" logic works, too -->
@default {
<ul>
@for (todo of todos.data(); track todo.id) {
<li>{{ todo.title }}</li>
} @empty {
<li>No todos found</li>
}
</ul>
}
}
`,
})
class TodosComponent {}
@Component({
selector: 'todos',
standalone: true,
template: `
@switch (todos.status()) {
@case ('pending') {
<span>Loading...</span>
}
@case ('error') {
<span>Error: {{ todos.error()?.message }}</span>
}
<!-- also status === 'success', but "else" logic works, too -->
@default {
<ul>
@for (todo of todos.data(); track todo.id) {
<li>{{ todo.title }}</li>
} @empty {
<li>No todos found</li>
}
</ul>
}
}
`,
})
class TodosComponent {}
如果你在访问 data 之前检查了 pending 和 error,TypeScript 也会正确地缩小 data 的类型。
除了 status 字段之外,你还将获得一个额外的 fetchStatus 属性,它具有以下选项
后台重新获取和 stale-while-revalidate 逻辑使 status 和 fetchStatus 的所有组合都成为可能。例如
因此请记住,查询可能处于 pending 状态,但实际上并没有获取数据。作为经验法则