查询是与唯一键绑定的、对异步数据源的声明式依赖。查询可用于任何基于 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 {
<!-- 此时可以假设 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 {
<!-- 此时可以假设 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>
}
<!-- 同样 status === 'success',但 "else" 逻辑也适用 -->
@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>
}
<!-- 同样 status === 'success',但 "else" 逻辑也适用 -->
@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 属性,其可选值为:
后台重新获取和“陈旧数据优先重新验证”逻辑使得 status 和 fetchStatus 的所有组合都可能出现。例如:
因此请记住,查询可能处于 pending 状态而实际上并未获取数据。作为经验法则: