当前位置: 首页 > news >正文

TanStack功能介绍和使用场景,对应 vue,react 完整使用示例

TanStack 功能介绍与使用场景

TanStack是一个专注于构建无头(Headless)类型安全框架无关的工具库集合。它的前身是著名的React Query团队,现已发展成为一个支持React, Vue, Solid, Svelte, Angular等多前端框架的生态系统。

其核心理念是:“学会一次,到处复用”。你只需要掌握一套 API 逻辑,就可以在任何支持的框架中使用,极大地降低了跨框架开发的学习成本和迁移成本。

核心功能模块与使用场景

模块原名核心功能典型使用场景
TanStack QueryReact Query异步状态管理。自动处理数据获取、缓存、后台同步、加载/错误状态、重试机制、窗口聚焦重新获取等。替代手写的axios+useState+useEffect组合;管理复杂的服务器状态;需要离线缓存或乐观更新的场景。
TanStack TableReact Table无头表格逻辑。提供排序、过滤、分页、分组、虚拟滚动等核心逻辑,不渲染任何 HTML,完全由你控制 UI。构建高度定制化的企业级数据表格;需要复杂交互(如多列排序、服务端分页)的后台管理系统。
TanStack Router-类型安全的路由。利用文件系统路由和强大的类型推导,实现参数、搜索查询的端到端类型安全。对类型安全要求极高的中大型应用;需要预加载数据或权限控制的复杂路由场景。
TanStack VirtualReact Virtual列表虚拟化。高效渲染超长列表或网格,只渲染可视区域内的 DOM 元素。聊天历史记录、无限滚动的信息流、大型数据表格的行虚拟化。
TanStack Form-表单管理。提供高性能的表单状态管理,支持复杂的验证逻辑(常与 Zod 结合)。复杂的动态表单、向导式表单、需要高性能验证的大型表单。
TanStack Start-全栈元框架。基于 Vite 和 TanStack Router,提供 SSR、流式传输、服务器函数等能力。构建类似 Next.js/Nuxt 的全栈应用,但希望使用 TanStack 生态的统一体验。

完整使用示例:Vue 3 vs React

以下将以最常用的TanStack Query(数据获取) 和TanStack Table(表格展示) 为例,对比 Vue 3 和 React 的完整用法。你会发现逻辑几乎一模一样,只是语法糖不同。

1. TanStack Query: 数据获取与缓存

场景:从 API 获取用户列表,并支持删除用户(突变)。

🅰️ Vue 3 示例 (@tanstack/vue-query)

安装:

npminstall@tanstack/vue-query

1. 初始化 (main.ts):

import{createApp}from'vue'import{VueQueryPlugin}from'@tanstack/vue-query'importAppfrom'./App.vue'constapp=createApp(App)app.use(VueQueryPlugin)// 注册插件app.mount('#app')

2. 使用组件 (UserList.vue):

<script setup lang="ts"> import { useQuery, useMutation, useQueryClient } from '@tanstack/vue-query' import axios from 'axios' // --- 1. 查询数据 (GET) --- const fetchUsers = async () => { const { data } = await axios.get('https://jsonplaceholder.typicode.com/users') return data } const { data, isLoading, error, refetch } = useQuery({ queryKey: ['users'], // 唯一的缓存键 queryFn: fetchUsers, staleTime: 1000 * 60 * 5, // 5分钟内数据视为新鲜,不重新请求 }) // --- 2. 修改数据 (DELETE) --- const queryClient = useQueryClient() const deleteMutation = useMutation({ mutationFn: (id: number) => axios.delete(`https://jsonplaceholder.typicode.com/users/${id}`), onSuccess: () => { // 成功后使 'users' 查询失效,触发自动重新获取 queryClient.invalidateQueries({ queryKey: ['users'] }) }, }) const handleDelete = (id: number) => { if(confirm('确定删除?')) { deleteMutation.mutate(id) } } </script> <template> <div> <h2>用户列表 (Vue 3)</h2> <!-- 加载状态 --> <div v-if="isLoading">加载中...</div> <!-- 错误状态 --> <div v-else-if="error">错误: {{ (error as Error).message }}</div> <!-- 数据列表 --> <ul v-else> <li v-for="user in data" :key="user.id"> {{ user.name }} <button @click="handleDelete(user.id)" :disabled="deleteMutation.isPending.value"> {{ deleteMutation.isPending.value ? '删除中...' : '删除' }} </button> </li> </ul> <button @click="refetch" style="margin-top: 20px;">手动刷新</button> </div> </template>
⚛️ React 示例 (@tanstack/react-query)

安装:

npminstall@tanstack/react-query

1. 初始化 (main.tsx):

import React from 'react' import ReactDOM from 'react-dom/client' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import App from './App' const queryClient = new QueryClient() // 创建客户端实例 ReactDOM.createRoot(document.getElementById('root')!).render( <QueryClientProvider client={queryClient}> {/* 包裹应用 */} <App /> </QueryClientProvider>, )

2. 使用组件 (UserList.tsx):

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import axios from 'axios' export default function UserList() { const queryClient = useQueryClient() // --- 1. 查询数据 (GET) --- const { data, isLoading, error, refetch } = useQuery({ queryKey: ['users'], queryFn: async () => { const { data } = await axios.get('https://jsonplaceholder.typicode.com/users') return data }, staleTime: 1000 * 60 * 5, }) // --- 2. 修改数据 (DELETE) --- const deleteMutation = useMutation({ mutationFn: (id: number) => axios.delete(`https://jsonplaceholder.typicode.com/users/${id}`), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['users'] }) }, }) if (isLoading) return <div>加载中...</div> if (error) return <div>错误: {(error as Error).message}</div> return ( <div> <h2>用户列表 (React)</h2> <ul> {data?.map((user: any) => ( <li key={user.id}> {user.name}{' '} <button onClick={() => handleDelete(user.id)} disabled={deleteMutation.isPending} > {deleteMutation.isPending ? '删除中...' : '删除'} </button> </li> ))} </ul> <button onClick={() => refetch()} style={{ marginTop: '20px' }}>手动刷新</button> </div> ) function handleDelete(id: number) { if (confirm('确定删除?')) { deleteMutation.mutate(id) } } }

对比总结: 逻辑配置(queryKey,queryFn,invalidateQueries)完全一致。Vue 中使用.value访问响应式对象(如isPending.value),而 React 直接访问属性。


2. TanStack Table: 高级表格

场景:展示用户数据,支持排序分页。TanStack Table 是 “Headless” 的,意味着它只提供逻辑(行、列、页码计算),你需要自己写<table>标签。

🅰️ Vue 3 示例 (@tanstack/vue-table)

安装:

npminstall@tanstack/vue-table

组件代码 (UserTable.vue):

<script setup lang="ts"> import { ref, computed } from 'vue' import { FlexRender, getCoreRowModel, getPaginationRowModel, getSortedRowModel, useVueTable, } from '@tanstack/vue-table' // 模拟数据 const data = ref([ { id: 1, name: 'Alice', age: 25 }, { id: 2, name: 'Bob', age: 30 }, { id: 3, name: 'Charlie', age: 35 }, { id: 4, name: 'David', age: 20 }, ]) // 定义列 const columns = [ { header: '姓名', accessorKey: 'name', cell: ({ getValue }: any) => getValue<string>(), }, { header: '年龄', accessorKey: 'age', cell: ({ getValue }: any) => getValue<number>(), }, ] // 初始化表格 const table = useVueTable({ data, columns, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), getSortedRowModel: getSortedRowModel(), state: { // 可以在此绑定响应式状态 }, }) </script> <template> <div> <table border="1" cellpadding="8"> <thead> <tr v-for="headerGroup in table.getHeaderGroups()" :key="headerGroup.id"> <th v-for="header in headerGroup.headers" :key="header.id" @click="header.column.toggleSorting()" style="cursor: pointer; user-select: none;" > <FlexRender :render="header.column.columnDef.header" :props="header.getContext()" /> {{ header.column.getIsSorted() ? (header.column.getIsSorted() === 'asc' ? ' 🔼' : ' 🔽') : '' }} </th> </tr> </thead> <tbody> <tr v-for="row in table.getRowModel().rows" :key="row.id"> <td v-for="cell in row.getVisibleCells()" :key="cell.id"> <FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" /> </td> </tr> </tbody> </table> <!-- 分页控件 --> <div style="margin-top: 10px;"> <button @click="table.setPageIndex(0)" :disabled="!table.getCanPreviousPage()" > 首页 </button> <button @click="table.previousPage()" :disabled="!table.getCanPreviousPage()" > 上一页 </button> <span> 第 {{ table.getState().pagination.pageIndex + 1 }} 页 </span> <button @click="table.nextPage()" :disabled="!table.getCanNextPage()" > 下一页 </button> <button @click="table.setPageIndex(table.getPageCount() - 1)" :disabled="!table.getCanNextPage()" > 末页 </button> </div> </div> </template>
⚛️ React 示例 (@tanstack/react-table)

安装:

npminstall@tanstack/react-table

组件代码 (UserTable.tsx):

import { useState } from 'react' import { flexRender, getCoreRowModel, getPaginationRowModel, getSortedRowModel, useReactTable, ColumnDef, } from '@tanstack/react-table' type Person = { id: number; name: string; age: number } const data: Person[] = [ { id: 1, name: 'Alice', age: 25 }, { id: 2, name: 'Bob', age: 30 }, { id: 3, name: 'Charlie', age: 35 }, { id: 4, name: 'David', age: 20 }, ] const columns: ColumnDef<Person>[] = [ { header: '姓名', accessorKey: 'name', cell: ({ getValue }) => getValue<string>(), }, { header: '年龄', accessorKey: 'age', cell: ({ getValue }) => getValue<number>(), }, ] export default function UserTable() { const [sorting, setSorting] = useState([]) const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 2 }) const table = useReactTable({ data, columns, state: { sorting, pagination }, onSortingChange: setSorting, onPaginationChange: setPagination, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), getSortedRowModel: getSortedRowModel(), }) return ( <div> <table border="1" cellPadding="8"> <thead> {table.getHeaderGroups().map((headerGroup) => ( <tr key={headerGroup.id}> {headerGroup.headers.map((header) => ( <th key={header.id} onClick={header.column.getToggleSortingHandler()} style={{ cursor: 'pointer', userSelect: 'none' }} > {flexRender(header.column.columnDef.header, header.getContext())} {{ asc: ' 🔼', desc: ' 🔽' }[header.column.getIsSorted() as string] ?? null} </th> ))} </tr> ))} </thead> <tbody> {table.getRowModel().rows.map((row) => ( <tr key={row.id}> {row.getVisibleCells().map((cell) => ( <td key={cell.id}> {flexRender(cell.column.columnDef.cell, cell.getContext())} </td> ))} </tr> ))} </tbody> </table> {/* 分页控件 */} <div style={{ marginTop: '10px' }}> <button onClick={() => table.setPageIndex(0)} disabled={!table.getCanPreviousPage()}> 首页 </button> <button onClick={() => table.previousPage()} disabled={!table.getCanPreviousPage()}> 上一页 </button> <span> 第 {table.getState().pagination.pageIndex + 1} 页 </span> <button onClick={() => table.nextPage()} disabled={!table.getCanNextPage()}> 下一页 </button> <button onClick={() => table.setPageIndex(table.getPageCount() - 1)} disabled={!table.getCanNextPage()} > 末页 </button> </div> </div> ) }

对比总结:

总结

TanStack 的最大优势在于统一性。一旦你理解了queryKey的概念或useTable的配置项,你就可以在 React、Vue 甚至 Solid 项目中无缝切换,无需重新学习新的 API。对于现代前端工程化而言,它是提升开发效率和代码质量的神器。

http://www.jsqmd.com/news/536298/

相关文章:

  • 深圳龙岗企业周花哪个好
  • ChatTTS长文本处理实战:AI辅助开发中的性能优化与避坑指南
  • 基于vue的便利店管理销售系统[vue]-计算机毕业设计源码+LW文档
  • 2026年比较好的黑芝麻油/精选黑芝麻公司推荐 - 品牌宣传支持者
  • 2026高校AIGC政策收紧,毕业生如何选对工具高效降论文ai率?
  • 新手福音:用快马AI生成你的第一个树莓派LED闪烁程序
  • 一点点了解数据通信,数据通信原理介绍(下)
  • 开发者的OpenClaw:用GLM-4.7-Flash构建CLI增强工具
  • 江苏高杆灯厂家全场景服务能力深度解析 - 优质品牌商家
  • 基于Vue的毕业设计系统实战:从需求拆解到生产部署
  • OpenClaw监控告警:ollama-QwQ-32B任务失败自动通知方案
  • 失业转行网安:我花 3 万报「黑客特训营」,结果学的是十年前的漏洞利用,现在靠扫端口月入 6K
  • 低成本运行OpenClaw:Qwen3-32B私有镜像Token消耗实测
  • OpenClaw新手必看:nanobot镜像的20个实用命令合集
  • WinRAR v7.21 Beta1 - 高效文件压缩加密解压缩软件
  • 实时语音变换开源工具完全指南:从环境搭建到高级优化的全流程实践
  • comsol18650圆柱形电池组流体直冷热管理仿真 采用电化学-热-流场耦合/集总电池-流场...
  • 接口电路设计的关键要点
  • OpenClaw+GLM-4.7-Flash:个人旅行计划自动生成系统
  • 计及力累积效应电力变压器绕组短路强度与稳定性研究 电力变压器作为电网系统的电力转换枢纽
  • 养老护理员培训行业白皮书:养老护理员考证/养老护理就业培训/成都养老护理员培训/成都养老护理培训学校/选择指南 - 优质品牌商家
  • VRPC:基于MQTT的嵌入式异步RPC通信框架
  • 物联网工程专业毕设实战:基于MQTT与边缘计算的低功耗设备监控系统设计
  • OpenClaw多通道实战:GLM-4.7-Flash同时接入飞书与钉钉
  • 你不知道的 Agent:原理、架构与工程实践
  • 双臂机器人Matlab仿真及程序源码
  • 隆阳区靠谱婚介所
  • java毕业设计基于springboot西岭雪山智慧景区管理系统
  • 蚁坊软件舆情监测系统:政企高效管理网络舆情的核心工具
  • Chrome WebRTC 性能优化实战:从延迟瓶颈到高效传输