更新记录
1.0.1(2025-07-14) 下载此版本
首次发布
平台兼容性
uni-app(4.45)
Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
---|---|---|---|---|---|---|---|---|
- | √ | √ | √ | √ | √ | √ | √ | - |
微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 快应用-华为 | 快应用-联盟 |
---|---|---|---|---|---|---|---|---|---|---|
√ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ |
useRequest Hook(uniapp vue3)
一个功能强大且高度可配置的 Vue 3 Composition API 请求 Hook,灵感来源于 ahooks 和 SWR。它内置了缓存、防抖、节流、轮询、重试、请求队列和并发控制等特性。
注意:如您下载使用本插件,请注意导入路径
特性
- 🚀 开箱即用:仅需一个 URL 即可发起请求。
- ✨ TypeScript 支持:提供完整的类型定义,保障代码健壮性。
- 🔄 自动请求与手动控制:支持组件挂载时自动请求,也支持手动触发。
- 🧠 状态管理:自动管理
loading
,data
,error
等响应式状态。 - 💾 缓存:内置请求缓存,可自定义缓存时间,避免重复请求。
- ⏳ 防抖 & 节流:轻松处理高频触发的请求场景。
- polling 轮询:支持轮询,可手动开始或停止。
- 🔗 依赖请求:支持根据响应式状态的变化来决定是否发起请求。
- ♻️ 错误重试:内置请求失败后的重试机制。
- 🎏 拦截器:支持请求、响应和错误拦截器,轻松实现全局逻辑处理(如 Token 添加、统一错误上报等)。
- 🔌 插件化:核心逻辑可通过插件扩展。
- 🛑 请求取消:可以取消正在进行的请求。
- 🚦 请求队列与并发控制:管理请求的执行顺序和并发数量。
快速上手
1. 全局配置与拦截器 (在 App.vue
中)
这是使用 useRequest
的第一步,也是最重要的一步。在应用的入口处(通常是 App.vue
)进行全局配置。
// App.vue
import {
setConfig,
setBaseURL,
addInterceptor,
createRequestInterceptor,
createResponseInterceptor,
createErrorInterceptor,
} from "uniapp-use-request";
// 1. 设置全局基础 URL
setBaseURL("https://api.example.com");
// 2. 设置全局默认配置
setConfig({
timeout: 15000,
showLoading: true, // 默认显示 uni.showLoading
loadingText: "加载中...",
showError: true, // 默认显示 uni.showToast
retryCount: 1, // 失败后默认重试1次
});
// 3. 添加请求拦截器
addInterceptor(
createRequestInterceptor((config) => {
console.log("[useRequest] 请求拦截器: ", config);
// 自动添加 Token
if (config.withToken) {
const token = uni.getStorageSync("token");
if (token) {
config.headers = {
...config.headers,
Authorization: `Bearer ${token}`,
};
}
}
return config;
})
);
// 4. 添加响应拦截器
addInterceptor(
createResponseInterceptor((response, config) => {
console.log("[useRequest] 响应拦截器: ", response);
// 这里可以对响应数据进行统一处理
// 例如,根据后端的业务码判断请求是否成功
const res = response as any;
if (res.code !== 200) {
// 抛出错误,会进入错误拦截器
throw new Error(res.message || "业务请求失败");
}
// 只返回 data 字段
return res.data;
})
);
// 5. 添加错误拦截器
addInterceptor(
createErrorInterceptor((error, config) => {
console.error("[useRequest] 错误拦截器: ", error);
// 这里可以对错误进行统一处理,例如上报错误日志、弹窗提示等
if (config.showError) {
uni.showToast({
title: error.message || "请求异常",
icon: "none",
});
}
// 返回错误对象,如果想在业务代码中继续处理错误
return error;
})
);
2. 在页面或组件中使用
默认自动请求
useRequest
默认在组件挂载后自动发起请求。
// pages/some-page/index.vue
import { useRequest } from "uniapp-use-request";
import { watch } from "vue";
const { data, loading, error } = useRequest<User>("/api/user/profile");
watch(data, (newData) => {
if (newData) {
console.log("获取到用户信息:", newData);
}
});
import { useRequest } from "uniapp-use-request";
const { data, loading, error } = useRequest("technew/index/indexConfig",{
params: {
type: "login",
},
method: "POST",
});
手动触发请求
设置 manual: true
,请求将不会自动发起,需要手动调用 run
方法。
const { loading, run: login } = useRequest("/api/login", {
manual: true,
method: "POST",
});
const handleLogin = async () => {
try {
const result = await login({ username: "test", password: "123" });
console.log("登录成功:", result);
} catch (e) {
console.error("登录失败:", e);
}
};
高级用法
缓存
设置 cacheTime
,在指定时间内,同样的请求将直接返回缓存数据。
const { data, loading } = useRequest("/api/articles", {
cacheTime: 5 * 60 * 1000, // 缓存5分钟
});
// 手动清除该请求的缓存
const { clearCache } = useRequest("/api/articles");
clearCache();
防抖与节流
适用于搜索等高频触发场景。
// 防抖:输入停止后 500ms 才发起请求
const { run: search } = useRequest("/api/search", {
manual: true,
debounce: true,
debounceTime: 500,
});
search();
// 节流:每 500ms 最多发起一次请求
const { run: submit } = useRequest("/api/submit", {
manual: true,
throttle: true,
throttleTime: 500,
});
submit();
轮询
通过 pollingInterval
设置轮询间隔。
const { data, polling, startPolling, stopPolling } = useRequest("/api/status", {
pollingInterval: 3000, // 每3秒轮询一次
pollingMaxCount: 10, // 最多轮询10次
});
// 手动停止
stopPolling();
// 手动开始
startPolling();
请求依赖 (ready
)
当 ready
的值为 true
时,请求才会发起。ready
可以是一个 ref
。
import { ref, computed } from "vue";
const userId = ref("");
const { data } = useRequest("/api/user/detail", {
// 使用 computed 确保 ready 是响应式的
ready: computed(() => !!userId.value),
params: {
id: userId, // useRequest 会自动解包 ref
},
});
// 在获取到 userId 后,请求会自动发出
userId.value = "user-123";
请求取消
可以手动取消一个正在进行的请求。
const { run, cancel, loading } = useRequest("/api/long-request", {
manual: true,
});
run();
// 3秒后如果请求还未完成,则取消它
setTimeout(() => {
if (loading.value) {
cancel();
}
}, 3000);
请求队列与并发控制
// 请求2: 获取提现列表 (高优先级)
const { data: userInfo, run } = useRequest("technew/my.Index/withdrawList", {
manual: true,
requestId: "user-init",
priority: 10, // 高优先级
method: "POST",
});
// 请求1: 获取登录配置 (低优先级)
const { data: loginConfig, run: getConfig } = useRequest("technew/index/indexConfig", {
manual: true,
requestId: "user-init",
priority: 1, // 低优先级
params: { type: "login" },
});
// 同时触发两个请求,它们将根据优先级排队执行
getConfig();
run();
API 参考
useRequest
参数
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
url | 请求地址或请求函数 | string \| ((params?: any) => string) |
- |
options | 请求配置 | RequestOptions |
{} |
RequestOptions
(部分常用)
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
manual |
是否手动触发 | boolean |
false |
params |
请求参数,会自动拼接到 URL 或作为 data |
Record<string, any> |
{} |
data |
请求体数据 | any |
- |
method |
请求方法 | GET POST 等 |
GET |
cacheTime |
缓存时间(ms),0 表示不缓存 |
number |
0 |
retryCount |
失败后重试次数 | number |
0 |
debounce |
是否开启防抖 | boolean |
false |
debounceTime |
防抖时间(ms) | number |
300 |
pollingInterval |
轮询间隔(ms),0 表示不轮询 |
number |
0 |
ready |
请求依赖,true 时发起请求 |
boolean \| Ref<boolean> |
true |
withToken |
是否在请求头中携带 Token | boolean |
true |
showLoading |
是否显示全局 uni.showLoading |
boolean |
false |
showError |
是否在错误拦截器中显示 uni.showToast |
boolean |
true |
useRequest
返回值
参数 | 说明 | 类型 |
---|---|---|
data |
响应数据 | Ref<T \| undefined> |
loading |
是否正在请求 | Ref<boolean> |
error |
错误对象 | Ref<Error \| null> |
polling |
是否正在轮询 | Ref<boolean> |
run |
手动触发请求的函数 | (...args) => Promise<T> |
cancel |
取消当前请求的函数 | () => void |
refresh |
使用上次参数重新请求 | () => Promise<T> |
clearCache |
清除当前请求的缓存 | () => void |
startPolling |
开始轮询 | () => void |
stopPolling |
停止轮询 | () => void |
完整使用示例 (场景化)
请注意:以下代码旨在提供
useRequest
hook 的各种使用场景示例,不可直接运行。正确的用法是将useRequest
导入到你的 Vue 组件的<script setup>
中使用。
import { useRequest } from "./index";
import { ref, watch, computed, Ref } from "vue";
// 定义一些可能用到的类型
type UserInfo = {
userId: string;
username: string;
avatar: string;
};
type Article = {
id: number;
title: string;
content: string;
};
// --- 示例场景 ---
/**
* 场景1: 基础用法 - 自动获取用户信息
* 组件挂载后,自动请求并展示用户信息。
*/
function useUserProfile() {
const {
data: userProfile,
loading,
error,
} = useRequest<UserInfo>("/api/user/profile");
// 使用 watch 监听数据变化
watch(userProfile, (newUser) => {
if (newUser) {
console.log("用户信息已更新:", newUser.username);
}
});
// 在模板中可以直接使用 userProfile, loading, error
// <view v-if="loading">加载中...</view>
// <view v-if="userProfile">欢迎, {{ userProfile.username }}</view>
}
/**
* 场景2: 手动触发 - 登录操作
* 点击按钮后,手动调用 `run` 方法来发起登录请求。
*/
function useLogin() {
const loginForm = ref({
username: "test",
password: "123",
});
const { run: performLogin, loading: isLoggingIn } = useRequest(
"/api/auth/login",
{
manual: true,
method: "POST",
}
);
const onLoginClick = async () => {
try {
// run 方法可以接受参数,这些参数会作为请求的 data
const token = await performLogin(loginForm.value);
uni.setStorageSync("token", token);
uni.showToast({ title: "登录成功" });
} catch (e) {
// 错误已由全局错误拦截器处理,这里可以不写
console.error("登录失败,具体原因已由拦截器提示。");
}
};
// 在模板中绑定 onLoginClick 到按钮上
// <button @click="onLoginClick" :loading="isLoggingIn">登录</button>
}
/**
* 场景3: 依赖请求 - 编辑时获取文章详情
* 只有当文章ID存在时,才发起请求获取详情。
*/
function useArticleDetail(articleId: Ref<number | null>) {
const { data: article, loading } = useRequest<Article>(
(id) => `/api/article/${id}`, // URL 可以是一个函数
{
// 当 `articleId` 有有效值时,`ready` 才为 true
ready: computed(() => !!articleId.value),
}
);
// 当外部的 articleId 变化时,如果它不为 null,请求会自动发起
// 例如:
// articleId.value = 123; // 这会触发请求
}
/**
* 场景4: 缓存 - 获取城市列表
* 城市列表这类不经常变动的数据,非常适合使用缓存。
*/
function useCityList() {
const { data: cityList, loading } = useRequest("/api/cities", {
cacheTime: 10 * 60 * 1000, // 缓存10分钟
});
// 在10分钟内,多次调用 useCityList 不会发出新的网络请求
}
/**
* 场景5: 取消请求
* 演示如何取消一个正在进行的请求。
*/
function useCancellableRequest() {
const { run, cancel, loading } = useRequest("/api/slow-request", {
manual: true,
});
const startRequest = () => {
run();
// 模拟一个场景:如果请求在2秒内没有完成,就自动取消它
setTimeout(() => {
if (loading.value) {
console.log("请求超时,正在取消...");
cancel();
}
}, 2000);
};
}