在上一篇《uni-app 网络请求终极选型》中,我们对比了四大主流请求方案。本文将深入讲解如何在 uni-app 项目中完整接入 alova,按照"安装 → 配置 → 使用"的步骤,让你的请求体验飞起来!
为什么选择 alova?
alova 不仅仅是一个请求库,更是一个完整的请求策略解决方案:
- 声明式 API:把 URL、参数、缓存策略封装进 Method 实例,一行 Hook 拿到响应式 loading / data / error,告别 try-catch
- 策略化:内置分页、防抖、轮询、断点续传等 20+ 场景 Hook,开箱即用
- 高性能:并发请求自动合并,多级缓存可离线,断网先读缓存再补发
- 类型友好:Method 与 Hook 自带完整 TS 推导
- 体积小巧:核心 4 KB,零依赖,Tree-shaking 只打包用到的代码
项目环境准备
本教程基于 WotDemo github.com/wot-ui/wot-... 项目,这是一个现代化的 uni-app 开发模板,包含:
- Vite + TypeScript 构建
- Vue 3 + Composition API
- UnoCSS 原子化CSS
- Pinia 状态管理
- ESLint + Prettier 代码规范
第一步:安装依赖
1.1 安装核心包
bash
# 推荐使用 pnpm
pnpm add alova @alova/adapter-uniapp
# 或使用 npm
npm install alova @alova/adapter-uniapp
# 或使用 yarn
yarn add alova @alova/adapter-uniapp
1.2 安装代码生成工具(推荐)
为了提升开发效率,强烈推荐安装 @alova/wormhole
代码生成工具:
bash
# 安装代码生成工具(开发依赖)
pnpm add -D @alova/wormhole
# 安装 Mock 数据支持(可选)
pnpm add @alova/mock
1.3 验证安装
安装完成后,检查 package.json
确认依赖已正确添加:
json
{
"dependencies": {
"alova": "^3.3.4",
"@alova/adapter-uniapp": "^2.0.14",
"@alova/mock": "^2.0.17"
},
"devDependencies": {
"@alova/wormhole": "^1.1.2"
}
}
第二步:环境配置
2.1 环境变量配置
在项目根目录创建环境变量文件:
.env.development
bash
# 开发环境配置
VITE_API_BASE_URL=http://localhost:3000/api
VITE_ENV_NAME=development
.env.production
bash
# 生产环境配置
VITE_API_BASE_URL=https://api.yourapp.com
VITE_ENV_NAME=production
.env.test
bash
# 测试环境配置
VITE_API_BASE_URL=https://test-api.yourapp.com
VITE_ENV_NAME=test
2.2 TypeScript 类型声明
在 src/types/env.d.ts
中添加环境变量类型声明:
typescript
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_API_BASE_URL: string
readonly VITE_ENV_NAME: string
// 更多环境变量...
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
2.3 在 alova 实例中使用环境变量
参考项目中的实际配置,在 src/api/core/instance.ts
中使用环境变量:
typescript
export const alovaInstance = createAlova({
// 使用环境变量配置 API 基础地址,提供默认值作为兜底
baseURL: import.meta.env.VITE_API_BASE_URL || 'https://petstore3.swagger.io/api/v3',
// 开发环境下的调试日志
beforeRequest: (method) => {
// 开发环境下记录请求日志和环境信息
if (import.meta.env.MODE === 'development') {
console.log(`[Alova Request] ${method.type} ${method.url}`, method.data || method.config.params)
console.log(`[API Base URL] ${import.meta.env.VITE_API_BASE_URL}`)
console.log(`[Environment] ${import.meta.env.VITE_ENV_NAME}`)
}
}
})
2.4 环境切换优势
通过环境变量配置,你可以:
- 开发环境:连接本地开发服务器,启用详细日志
- 测试环境:连接测试服务器进行集成测试
- 生产环境:连接正式的生产服务器,关闭调试日志
- 灵活切换:通过修改环境变量文件快速切换不同环境
第三步:配置代码生成工具
3.1 创建 alova.config.ts 配置文件
在项目根目录创建 alova.config.ts
配置文件:
typescript
import type { Config } from '@alova/wormhole'
export default <Config>{
generator: [
{
// OpenAPI 文档地址(支持本地文件或在线地址)
input: 'https://petstore3.swagger.io/api/v3/openapi.json',
// 文档平台类型
platform: 'swagger',
// 生成代码的输出目录
output: 'src/api',
// 响应数据的媒体类型
responseMediaType: 'application/json',
// 请求体数据的媒体类型
bodyMediaType: 'application/json',
// 生成的 API 版本
version: 3,
// 生成代码类型
type: 'typescript',
// 全局 API 名称
global: 'Apis',
// API 处理函数
handleApi: (apiDescriptor) => {
// 过滤掉已废弃的 API
if (apiDescriptor.deprecated) {
return undefined
}
return apiDescriptor
},
},
],
// 自动更新配置
autoUpdate: {
// 编辑器启动时更新
launchEditor: true,
// 每5分钟检查更新
interval: 5 * 60 * 1000,
},
}
2.2 添加生成命令
在 package.json
中添加代码生成命令:
json
{
"scripts": {
"alova-gen": "alova gen -f"
}
}
2.3 生成 API 代码
运行命令生成 API 接口代码:
bash
# 生成 API 代码
pnpm run alova-gen
# 或直接使用
pnpm run alova gen -f
2.4 生成后的目录结构
python
src/
├── api/
│ ├── apiDefinitions.ts # 自动生成的 API 定义
│ ├── createApis.ts # 自动生成的 API 创建函数
│ ├── globals.d.ts # 自动生成的全局类型定义
│ ├── index.ts # 统一导出文件
│ ├── core/ # 核心配置目录
│ │ └── instance.ts # alova 实例配置
│ └── mock/ # Mock 数据目录(可选)
2.5 配置 alova 实例
在 src/api/core/instance.ts
中创建 alova 实例,参考项目实际配置:
typescript
import { createAlova } from 'alova'
import vueHook from 'alova/vue'
import AdapterUniapp from '@alova/adapter-uniapp'
import mockAdapter from '../mock/mockAdapter'
import { handleAlovaError, handleAlovaResponse } from './handlers'
export const alovaInstance = createAlova({
// 基础URL - 支持环境变量配置
baseURL: import.meta.env.VITE_API_BASE_URL || 'https://petstore3.swagger.io/api/v3',
// 使用 uni-app 适配器,支持 Mock 数据
...AdapterUniapp({
mockRequest: mockAdapter,
}),
// Vue 3 状态钩子
statesHook: vueHook,
// 全局请求拦截器
beforeRequest: (method) => {
// 为 POST/PUT/PATCH 请求添加 Content-Type
if (['POST', 'PUT', 'PATCH'].includes(method.type)) {
method.config.headers['Content-Type'] = 'application/json'
}
// 为 GET 请求添加时间戳防止缓存
if (method.type === 'GET' && CommonUtil.isObj(method.config.params)) {
method.config.params._t = Date.now()
}
// 开发环境下记录请求日志
if (import.meta.env.MODE === 'development') {
console.log(`[Alova Request] ${method.type} ${method.url}`, method.data || method.config.params)
console.log(`[API Base URL] ${import.meta.env.VITE_API_BASE_URL}`)
console.log(`[Environment] ${import.meta.env.VITE_ENV_NAME}`)
}
},
// 全局响应拦截器
responded: {
// 成功处理器 - 在 handlers.ts 中定义
onSuccess: handleAlovaResponse,
// 错误处理器 - 在 handlers.ts 中定义
onError: handleAlovaError,
// 完成处理器 - 成功或失败后都会执行
onComplete: async () => {
// 可以在这里进行清理或日志记录
},
},
// 请求超时时间(60秒)
timeout: 60000,
// 全局关闭缓存(设置为 null)
cacheFor: null,
})
export default alovaInstance
响应和错误处理器
在 src/api/core/handlers.ts
中定义统一的响应和错误处理逻辑:
typescript
import type { Method } from 'alova'
import router from '@/router'
// 自定义 API 错误类
export class ApiError extends Error {
code: number
data?: any
constructor(message: string, code: number, data?: any) {
super(message)
this.name = 'ApiError'
this.code = code
this.data = data
}
}
// API 响应结构类型
interface ApiResponse {
code: number
msg?: string
data?: any
success?: boolean
total?: number
more?: boolean
}
// 处理成功响应
export async function handleAlovaResponse(response: UniApp.RequestSuccessCallbackResult) {
const globalToast = useGlobalToast()
const { statusCode, data } = response
// 处理 401/403 未授权错误
if (statusCode === 401 || statusCode === 403) {
globalToast.error({ msg: '登录已过期,请重新登录!', duration: 500 })
setTimeout(() => {
router.replaceAll({ name: 'login' })
}, 500)
throw new ApiError('登录已过期,请重新登录!', statusCode, data)
}
// 处理 HTTP 错误状态码
if (statusCode >= 400) {
globalToast.error(`请求失败,状态码: ${statusCode}`)
throw new ApiError(`请求失败,状态码: ${statusCode}`, statusCode, data)
}
// 开发环境下记录响应日志
if (import.meta.env.MODE === 'development') {
console.log('[Alova Response]', data)
}
return data as ApiResponse
}
// 处理请求错误
export function handleAlovaError(error: any, method: Method) {
const globalToast = useGlobalToast()
// 开发环境下记录错误日志
if (import.meta.env.MODE === 'development') {
console.error('[Alova Error]', error, method)
}
// 处理不同类型的错误
if (error.name === 'NetworkError') {
globalToast.error('网络错误,请检查您的网络连接')
}
else if (error.name === 'TimeoutError') {
globalToast.error('请求超时,请重试')
}
else if (error instanceof ApiError) {
globalToast.error(error.message || '请求失败')
}
else {
globalToast.error('发生意外错误')
}
throw error
}
关键配置说明:
- 环境变量支持 :使用
import.meta.env.VITE_API_BASE_URL
支持不同环境配置 - Mock 数据集成 :通过
mockAdapter
支持开发阶段的数据模拟 - Vue 3 集成 :使用
vueHook
确保与 Vue 3 响应式系统的兼容 - 模块化处理 :将响应和错误处理逻辑分离到
handlers.ts
文件中 - 统一错误处理 :自定义
ApiError
类,统一处理各种错误场景 - 自动登录跳转:401/403 错误时自动跳转到登录页面
- 开发调试:在开发环境下自动记录请求和响应日志
第三步:在页面中使用
3.1 自动导入配置(开发体验优化)
WotDemo 项目通过 unplugin-auto-import
配置了自动导入,开发者无需手动引入 API 和 alova hooks。
在 vite.config.ts
中的配置:
typescript
AutoImport({
imports: [
'vue',
'@vueuse/core',
'pinia',
'uni-app',
{
from: 'alova/client',
imports: ['usePagination', 'useRequest', 'useWatcher', 'useForm'],
}
],
// 自动导入 src/api 目录下的所有导出
dirs: ['src/composables', 'src/store', 'src/utils', 'src/api'],
dts: 'src/auto-imports.d.ts',
vueTemplate: true,
})
这意味着你可以直接使用,无需手动导入:
typescript
// ✅ 无需手动导入,直接使用
const { data, loading } = useRequest(Apis.pet.findPetsByStatus)
// ❌ 不再需要这样手动导入
// import { useRequest } from 'alova'
// import { Apis } from '@/api'
3.2 基础数据获取
参考项目中的 src/pages/request/index.vue
:
typescript
// 🎉 直接使用,无需导入!
// useRequest 和 Apis 都已自动导入
// 获取宠物列表
const {
data,
loading,
error,
send: loadPetData
} = useRequest(
(status: 'available' | 'pending' | 'sold' = 'available') => Apis.pet.findPetsByStatus({
params: { status }
}),
{
immediate: false,
initialData: []
}
)
// 用户登录演示
const {
data: loginResult,
loading: loginLoading,
send: performLogin
} = useRequest(
(username: string, password: string) => Apis.user.loginUser({
params: { username, password }
}),
{
immediate: false
}
)
// 演示函数
function demoLoadPets() {
loadPetData('available')
}
function demoLogin() {
performLogin('testuser', 'testpass')
}
3.2 监听式请求
typescript
import { ref } from 'vue'
import { useWatcher } from 'alova'
import { Apis } from '@/api'
// 响应式状态
const petStatus = ref<'available' | 'pending' | 'sold'>('available')
// 监听状态变化,自动发送请求
const {
data: petList,
loading: petLoading,
error: petError
} = useWatcher(
() => Apis.pet.findPetsByStatus({
params: { status: petStatus.value }
}),
[petStatus],
{
immediate: true,
debounce: 300
}
)
// 切换状态
function changeStatus(status: 'available' | 'pending' | 'sold') {
petStatus.value = status
}
3.3 分页请求
typescript
import { usePagination } from 'alova'
import { Apis } from '@/api'
// 分页请求
const {
data: inventoryList,
loading: listLoading,
page,
pageSize,
total,
isLastPage,
reload
} = usePagination(
(page, pageSize) => Apis.store.getInventory(),
{
initialPage: 1,
initialPageSize: 10,
preloadPreviousPage: true,
preloadNextPage: true,
total: res => Object.keys(res).length,
data: res => Object.entries(res).map(([key, value]) => ({ name: key, count: value }))
}
)
// 加载更多
function loadMore() {
if (!isLastPage.value && !listLoading.value) {
page.value++
}
}
3.4 表单提交
typescript
import { reactive } from 'vue'
import { useForm } from 'alova'
import { Apis } from '@/api'
// 表单数据
const formData = reactive({
name: '',
status: 'available' as const,
category: { id: 1, name: 'Dogs' },
photoUrls: ['https://example.com/photo.jpg']
})
// 表单提交
const {
loading: submitting,
send: submitForm,
onSuccess,
onError
} = useForm(
formData => Apis.pet.addPet({ data: formData }),
{
immediate: false,
resetAfterSubmitting: true
}
)
// 成功回调
onSuccess(() => {
const globalToast = useGlobalToast()
globalToast.success('添加成功')
})
// 错误回调
onError((error) => {
const globalToast = useGlobalToast()
globalToast.error(error.message || '添加失败')
})
// 提交表单
function handleSubmit() {
if (!formData.name) {
const globalToast = useGlobalToast()
globalToast.warning('请输入宠物名称')
return
}
submitForm(formData)
}
第四步:开发环境优化
4.1 使用 @alova/wormhole 的优势
使用代码生成工具的主要优势:
- 自动同步:API 文档更新时自动重新生成代码
- 类型安全:自动生成完整的 TypeScript 类型定义
- 减少错误:避免手动编写 API 时的拼写错误
- 提升效率:无需手动维护大量的 API 接口代码
4.2 Mock 数据支持
在开发阶段,可以使用 alova 的 Mock 功能:
typescript
import { createAlovaMockAdapter } from '@alova/mock'
// Mock 适配器
const mockAdapter = createAlovaMockAdapter([
{
path: '/pet/{petId}',
method: 'GET',
response: ({ pathParams }) => ({
id: pathParams.petId,
name: 'Mock Pet',
status: 'available',
category: { id: 1, name: 'Dogs' },
photoUrls: ['https://example.com/mock.jpg']
})
}
], {
// 延迟响应
delay: [300, 800],
// Mock 开关
enable: process.env.NODE_ENV === 'development'
})
// 在 alova 实例中使用
export default createAlova({
baseURL: 'https://petstore3.swagger.io/api/v3',
...mockAdapter,
// 其他配置...
})
4.3 环境配置
创建 src/api/core/config.ts
管理不同环境的配置:
typescript
// 环境配置
const config = {
development: {
baseURL: 'https://petstore3.swagger.io/api/v3',
timeout: 10000,
enableMock: true
},
production: {
baseURL: 'https://api.yourproject.com',
timeout: 5000,
enableMock: false
}
}
export const apiConfig = config[process.env.NODE_ENV as keyof typeof config] || config.development
总结
通过本文的四个步骤,我们已经完整掌握了在 uni-app 中使用 alova 的全流程:
✅ 完成的配置
- 安装依赖 - 正确安装 alova 核心库和适配器
- 配置代码生成工具 - 使用 @alova/wormhole 自动生成 API 代码
- 页面使用 - 掌握四种常见请求场景
- 开发优化 - Mock 数据、环境配置
- 性能优化 - 缓存策略、预加载、错误处理
🚀 核心优势
- 开发效率提升:智能缓存和请求去重减少重复请求
- 用户体验优化:静默提交和预加载提升响应速度
- 代码质量保证:TypeScript 支持和统一错误处理
- 维护成本降低:模块化设计和最佳实践
📚 进阶学习
- alova 官方文档 alova.js.org/zh-CN/
- WotDemo 项目地址 github.com/wot-ui/wot-...
- alova uni-app 适配器文档 alova.js.org/zh-CN/resou...
- alova 扩展集成 alova.js.org/zh-CN/tutor...
现在你可以在自己的 uni-app 项目中应用这些配置,打造高性能、用户体验优秀的跨端应用!wot demo 已接入 alova,你可以可以直接使用wot-demo进行体验。
相关文章
告别 HBuilderX,拥抱现代化!这个模板让 uni-app 开发体验起飞
Vue3 uni-app 主包 2 MB 危机?1 个插件 10 分钟瘦身
uni-app 也能像 Vue 一样用 App.vue 了?这款插件做到了!
有问题欢迎在评论区讨论,让我们一起打造更好的 uni-app 开发体验! 🚀