vue2项目里怎么用vue-query?从基础到实践的常见问题解答
做vue2项目时,每次写接口请求都要手动管加载状态、缓存、重复请求,是不是头大?要是有个工具能自动搞定这些,代码还简洁,那该多爽!vue-query就是干这个的,但不少同学在vue2里用它时,总会碰到“咋安装?咋发请求?分页咋处理?”这些问题,今天就从基础到实践,把vue2 + vue-query的常见问题拆明白,看完你也能轻松用它搞定数据层!
vue-query是啥?vue2项目为啥要考虑用它?
vue-query是专门管理数据请求与状态的工具库,不管是查询接口(query)还是增删改操作(mutation),它都能自动处理缓存、重复请求拦截、加载状态维护、后台数据同步这些“脏活”。
那vue2项目里手动写请求有多麻烦?举个例子:用axios调接口时,得自己定义loading
变量,请求前设为true
、成功/失败后设为false
;还要手动把响应数据存到data
里;遇到重复请求,得写拦截器去重;想做缓存,还得用localStorage或vuex存数据……每次新增接口,这些重复代码都得写一遍,又累又容易出错。
而vue-query把这些事儿全封装了:发请求时自动管理loading
/error
状态,相同标识的请求自动缓存,页面切回来时自动刷新“过期”数据,甚至连请求重试、分页缓存都内置好了,对vue2老项目来说,不用重构整个架构,只在数据请求层替换,就能让代码量少一大半,维护性直接起飞。
vue2里咋安装和初始化vue-query?
首先得选对版本!因为vue-query现在叫@tanstack/vue-query
,vue2要装v3版本(v4以上主要支持vue3 + Composition API,vue2用v3更稳),命令行执行:
npm install @tanstack/vue-query@3
安装完后,要在main.js
里全局注册插件,代码示例:
import Vue from 'vue' import { VueQueryPlugin } from '@tanstack/vue-query' Vue.use(VueQueryPlugin, { queryClientConfig: { defaultOptions: { queries: { staleTime: 5 * 60 * 1000, // 5分钟内数据视为“新鲜”,不自动请求 cacheTime: 10 * 60 * 1000, // 缓存数据保留10分钟 retry: 3, // 请求失败自动重试3次 }, }, }, })
这里staleTime
和cacheTime
要注意区别:staleTime
是数据的“新鲜期”,过期后下次访问会后台静默更新;cacheTime
是数据的“缓存期”,过期后会被垃圾回收,下次得重新请求,根据项目需求调整这两个值,能平衡性能和数据新鲜度。
发第一个请求,vue-query基本流程是啥?
用useQuery
就能发查询请求,核心是两个参数:queryKey
(请求的唯一标识,一般用数组,方便传参)和queryFn
(实际发请求的函数)。
举个“获取文章列表”的例子(假设接口是/api/articles
):
<template> <div> <div v-if="isLoading">加载中...</div> <div v-else-if="isError">{{ error.message }}</div> <div v-else> <ul> <li v-for="item in data" :key="item.id">{{ item.title }}</li> </ul> </div> </div> </template> <script> import { useQuery } from '@tanstack/vue-query' import axios from 'axios' export default { name: 'ArticleList', setup() { // queryKey用数组,方便后续加参数(比如分页) const queryKey = ['articles'] // queryFn返回Promise,封装接口请求 const queryFn = () => axios.get('/api/articles').then(res => res.data) // 调用useQuery,拿到数据和状态 const { data, isLoading, isError, error } = useQuery(queryKey, queryFn) return { data, isLoading, isError, error } }, } </script>
这里queryKey
必须唯一!如果两个组件用了一样的queryKey
,vue-query会自动复用缓存,避免重复请求,比如另一个组件也查文章列表,用相同的['articles']
,就会直接读缓存,不用再调接口。
列表分页场景,vue-query咋处理?
分页时,请求参数一般有page
和size
,这时候把参数放到queryKey
里,vue-query就能自动识别参数变化、触发重新请求,用keepPreviousData
能让分页切换时,旧数据不消失,用户体验更丝滑。
看例子(假设接口是/api/articles?page=xxx&size=xxx
):
<template> <div> <button @click="page--" :disabled="page === 1">上一页</button> <button @click="page++">下一页</button> <div v-if="isLoading">加载中...</div> <ul v-else> <li v-for="item in data" :key="item.id">{{ item.title }}</li> </ul> <div v-if="isPreviousData">正在加载新页,暂时显示上一页内容...</div> </div> </template> <script> import { useQuery } from '@tanstack/vue-query' import axios from 'axios' import { ref } from 'vue' export default { name: 'ArticlePage', setup() { const page = ref(1) const size = ref(10) // queryKey包含page和size,参数变化时自动重新请求 const queryKey = ['articles', page, size] // queryFn里用page和size传参 const queryFn = () => axios.get(`/api/articles?page=${page.value}&size=${size.value}`).then(res => res.data) // useQuery配置keepPreviousData,分页时保留上一页数据 const { data, isLoading, isPreviousData } = useQuery(queryKey, queryFn, { keepPreviousData: true, }) return { data, isLoading, isPreviousData, page } }, } </script>
keepPreviousData
的作用是:当queryKey
变化(比如page
从1变2),新请求还没回来时,data
还是上一页的内容,不会空白;等新数据到了再替换,用户点分页时,界面不会“闪一下”,体验好很多。
增删改操作(mutation),vue-query咋做?
查询用useQuery
,增删改这类“修改数据”的操作得用useMutation
,它的逻辑是:触发mutation时执行mutationFn
,成功后可以手动让相关查询的缓存失效(比如新增文章后,列表页重新请求最新数据)。
举个“新增文章”的例子:
<template> <div> <input v-model="title" placeholder="文章标题" /> <button @click="createArticle" :disabled="isLoading"> {{ isLoading ? '提交中...' : '发布文章' }} </button> <div v-if="error">{{ error.message }}</div> </div> </template> <script> import { useMutation, useQueryClient } from '@tanstack/vue-query' import axios from 'axios' import { ref } from 'vue' export default { name: 'CreateArticle', setup() { const title = ref('') const queryClient = useQueryClient() // 获取全局queryClient // mutationFn封装POST请求 const mutationFn = (title) => axios.post('/api/articles', { title }) // 调用useMutation,配置成功后回调 const { mutate: createArticle, isLoading, error } = useMutation(mutationFn, { onSuccess: () => { // 新增成功后,让articles列表的缓存失效,自动重新请求 queryClient.invalidateQueries(['articles']) }, }) return { title, createArticle, isLoading, error } }, } </script>
这里invalidateQueries(['articles'])
的作用是:找到所有queryKey
包含articles
的查询,标记它们为“过期”;下次组件访问这些查询时,会自动重新请求接口,这样列表页就能实时显示新增的文章,不用手动更新数据。
vue2用vue-query常见的坑,咋避?
- 版本装错:vue2必须用
@tanstack/vue-query@3
,装成v4会因依赖vue3 API报错,装包时要指定版本:npm i @tanstack/vue-query@3
。 - queryKey写得乱:如果多个请求用了一样的
queryKey
,会导致缓存冲突,文章列表”和“热门文章列表”,queryKey
都用['articles']
就会互相覆盖,解决方法:给不同逻辑的请求加唯一标识,比如['articles', 'hot']
和['articles', 'all']
。 - staleTime和cacheTime没搞懂:比如把
staleTime
设为0,数据一回来就标记为“过期”,下次访问会立刻重新请求,导致请求太频繁;cacheTime
设太小,页面切回去时缓存已被清除,又得重新请求,得根据业务调:后台管理系统数据更新慢,staleTime
可以设大(比如10分钟);资讯类App数据新鲜度高,staleTime
设小(比如1分钟)。 - 和vuex的边界分不清:vue-query管“数据请求+缓存+状态”,vuex管“全局业务状态共享”(比如用户权限、主题配置),如果只是接口请求的状态,用vue-query更高效;如果是多组件共享的业务状态,还是得用vuex,别把两者的活搞混,不然代码会乱。
和axios、vue-resource比,vue-query优势在哪?
很多同学习惯直接用axios写请求,但对比下来,vue-query能省超多重复代码:
- 自动状态管理:axios得自己写
loading = true/false
,vue-query直接给isLoading
、isError
这些状态。 - 智能缓存:相同
queryKey
的请求自动缓存,页面刷新或组件复用都不重复请求;axios得自己存localStorage或vuex,还得处理缓存失效。 - 后台同步:用户切到其他标签页再切回来,vue-query会自动检查数据是否“过期”,然后静默更新;axios要做这个,得监听
visibilitychange
事件、自己写逻辑。 - 请求重试:接口失败时,vue-query能自动重试(还能配次数);axios得自己写重试拦截器。
简单说,vue-query把“数据请求环节的脏活累活”全做了,你只需要关心业务逻辑,对vue2项目来说,接入成本低、收益大——代码更简洁,维护更轻松,用户体验(比如分页不闪、后台自动更新)也更好。
看完这些,你应该对vue2里用vue-query有清晰思路了:从安装到发请求,从查询到修改,再到避坑和对比优势,核心就是让它帮你搞定数据层的繁琐事儿,要是你项目里还在手动管请求状态、缓存,不妨试试vue-query,体验下“写请求像呼吸一样简单”的感觉~要是实操中碰到新问题,评论区随时喊我,咱一起解决!
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。