Alova 深入指南
什么是 Alova?
Alova 是一个轻量级、面向前端的请求策略库,旨在简化 API 调用、优化性能并提升开发效率。它通过声明式的 Method
实例管理请求,将复杂的请求逻辑(如参数、缓存、状态管理)高度抽象,号称将传统 7 步请求流程简化为“一步到位”。Alova 与 Vue 3 的 Composition API 深度集成,提供了响应式状态管理、丰富的业务场景策略以及强大的扩展性,特别适合现代前端开发。
核心特点
- 声明式请求:通过
Method
实例封装请求信息,减少手动编码。 - 响应式状态管理:与 Vue 3 的响应式系统无缝绑定,自动更新视图。
- 内置策略:支持分页、表单提交、文件上传等 20+ 种业务场景,简化复杂逻辑。
- 高性能:通过请求共享、缓存和预加载机制,减少网络请求,提升用户体验。
- TypeScript 支持:提供完整的类型推导,增强代码健壮性。
- 跨框架兼容:虽以 Vue 3 为例,但也支持 React、Svelte 等。
Alova 的设计理念是将 API 调用的配置、状态和行为集中到一个 Method
实例中,开发者只需关注业务逻辑,无需处理繁琐的请求细节。
Alova 的工作原理
Alova 的核心机制包括 方法代理设计、状态代理设计 和 请求策略中间件,以下详细解析。
方法代理设计
每个 API 请求都被封装为一个 Method
实例,包含 URL、请求方法、参数、头信息、缓存策略等。开发者通过 alovaInstance.Get
、Post
等方法创建 Method
实例,调用时无需手动拼接请求逻辑。例如:
const todoListGetter = alovaInstance.Get('/todos', {
params: { page: 1, size: 10 },
cacheFor: 1000 * 60, // 缓存 1 分钟
transformData: (rawData) => rawData.list
});
Method
实例不仅定义了请求,还支持复用、链式调用和动态修改,适合复杂项目中的 API 管理。
状态代理设计
Alova 通过 statesHook
与 Vue 3 的响应式系统(如 ref
和 reactive
)深度集成。使用 useRequest
或 useWatcher
等 Hook,请求状态(如 loading
、data
、error
)会自动变为响应式,状态变化直接触发视图更新。例如:
const { loading, data, error } = useRequest(todoListGetter);
当请求完成或失败时,data
或 error
会自动更新,Vue 3 会同步刷新视图。
请求策略中间件
Alova 提供了中间件机制,允许开发者在请求前后插入自定义逻辑。例如,自动添加认证头:
const alovaInstance = createAlova({
beforeRequest(method) {
method.config.headers.Authorization = `Bearer ${localStorage.getItem('token')}`;
}
});
此外,Alova 内置了 20+ 种策略(如分页、表单提交),通过中间件实现,极大简化了业务逻辑。
在 Vue 3 中使用 Alova
以下以 Vue 3 的 Composition API 和 <script setup>
为主,展示 Alova 在多种场景下的使用方式。
1. 环境搭建
安装
npm install alova alova/vue alova/fetch
创建 Alova 实例
在项目根目录创建一个 alova.js
文件:
import { createAlova } from 'alova';
import adapterFetch from 'alova/fetch';
import VueHook from 'alova/vue';
export const alovaInstance = createAlova({
baseURL: 'https://api.example.com',
statesHook: VueHook, // Vue 3 响应式 Hook
requestAdapter: adapterFetch(), // 使用 fetch 适配器
responded: response => response.json(), // 响应数据处理
beforeRequest(method) {
// 添加认证头
method.config.headers.Authorization = `Bearer ${localStorage.getItem('token')}`;
},
errorHandler(error) {
console.error('Request failed:', error);
return Promise.reject(error);
}
});
配置 TypeScript(可选)
为确保类型安全,添加类型定义:
import { Alova } from 'alova';
declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$alova: Alova;
}
}
2. 基本请求:使用 useRequest
useRequest
是最常用的 Hook,用于发送请求并管理状态。以下是一个获取待办事项列表的示例:
<script setup>
import { useRequest } from 'alova/vue';
import { alovaInstance } from './alova';
// 定义 Method 实例
const todoListGetter = alovaInstance.Get('/todos', {
params: { page: 1, size: 10 },
cacheFor: 1000 * 60, // 缓存 1 分钟
transformData: (rawData) => rawData.list
});
// 使用 useRequest
const { loading, data, error, send } = useRequest(todoListGetter, {
initialData: [], // 初始数据
immediate: true // 立即发送请求
});
// 手动触发请求
const handleRefresh = () => send();
</script>
<template>
<div>
<div v-if="loading">加载中...</div>
<div v-else-if="error">{{ error.message }}</div>
<div v-else>
<ul>
<li v-for="todo in data" :key="todo.id">{{ todo.title }}</li>
</ul>
<button @click="handleRefresh">刷新</button>
</div>
</div>
</template>
说明:
loading
、data
、error
是响应式对象,自动触发视图更新。send
用于手动触发请求,适合需要用户交互的场景。cacheFor
设置缓存时间,减少重复请求。
3. 动态请求:使用 useWatcher
当请求依赖动态参数(如分页、搜索条件)时,使用 useWatcher
监听参数变化并自动触发请求。
<script setup>
import { ref } from 'vue';
import { useWatcher } from 'alova/vue';
import { alovaInstance } from './alova';
const page = ref(1);
const size = ref(10);
const search = ref('');
// 定义分页请求
const todoListGetter = () => alovaInstance.Get('/todos', {
params: { page: page.value, size: size.value, search: search.value },
cacheFor: 1000 * 60,
transformData: (rawData) => rawData.list
});
// 使用 useWatcher
const { loading, data } = useWatcher(todoListGetter, [page, size, search], {
initialData: [],
immediate: true
});
// 分页控制
const nextPage = () => page.value++;
const prevPage = () => page.value > 1 && page.value--;
</script>
<template>
<div>
<input v-model="search" placeholder="搜索待办事项" />
<div v-if="loading">加载中...</div>
<div v-else>
<ul>
<li v-for="todo in data" :key="todo.id">{{ todo.title }}</li>
</ul>
<button @click="prevPage" :disabled="page === 1">上一页</button>
<button @click="nextPage">下一页</button>
</div>
</div>
</template>
说明:
useWatcher
监听page
、size
和search
,任何变化都会触发请求。- 适用于分页、搜索、过滤等动态场景。
4. 表单提交
Alova 的表单策略支持草稿保存、验证和多页表单。以下是一个提交表单的示例:
<script setup>
import { ref } from 'vue';
import { useRequest } from 'alova/vue';
import { alovaInstance } from './alova';
const form = ref({ name: '', email: '' });
// 定义表单提交请求
const submitForm = alovaInstance.Post('/form', form, {
transformData: (rawData) => rawData.result
});
const { loading, send, onSuccess } = useRequest(submitForm, { immediate: false });
// 监听提交成功
onSuccess(({ data }) => {
alert('提交成功: ' + JSON.stringify(data));
});
// 提交表单
const handleSubmit = async () => {
if (!form.value.name || !form.value.email) {
alert('请填写完整信息');
return;
}
await send();
};
</script>
<template>
<div>
<input v-model="form.name" placeholder="姓名" />
<input v-model="form.email" placeholder="邮箱" />
<button :disabled="loading" @click="handleSubmit">
{{ loading ? '提交中...' : '提交' }}
</button>
</div>
</template>
说明:
useRequest
的immediate: false
确保请求手动触发。onSuccess
用于处理提交成功后的逻辑。
5. 文件上传
Alova 支持文件上传,自动处理 FormData
和进度监控。
<script setup>
import { ref } from 'vue';
import { useRequest } from 'alova/vue';
import { alovaInstance } from './alova';
const file = ref(null);
// 定义文件上传请求
const uploadFile = (fileData) => alovaInstance.Post('/upload', { file: fileData }, {
headers: { 'Content-Type': 'multipart/form-data' }
});
const { loading, send, onProgress } = useRequest(uploadFile, { immediate: false });
const progress = ref(0);
// 监听上传进度
onProgress(({ loaded, total }) => {
progress.value = Math.round((loaded / total) * 100);
});
// 处理文件选择
const handleFileChange = (event) => {
file.value = event.target.files[0];
};
// 触发上传
const handleUpload = async () => {
if (file.value) {
await send(file.value);
alert('上传成功');
}
};
</script>
<template>
<div>
<input type="file" @change="handleFileChange" />
<button :disabled="loading" @click="handleUpload">
{{ loading ? `上传中 (${progress}%)` : '上传' }}
</button>
</div>
</template>
说明:
onProgress
提供上传进度反馈。FormData
自动处理文件数据。
6. 请求拦截与错误处理
通过 Alova 的中间件,可以拦截请求和响应,统一处理认证、错误等逻辑。
<script setup>
import { useRequest } from 'alova/vue';
import { alovaInstance } from './alova';
// 定义请求
const todoGetter = alovaInstance.Get('/todos/1', {
cacheFor: 0,
transformData: (rawData) => rawData.data
});
const { loading, data, error, onError } = useRequest(todoGetter);
// 错误处理
onError(({ error }) => {
if (error.status === 401) {
alert('未授权,请登录');
}
});
</script>
<template>
<div>
<div v-if="loading">加载中...</div>
<div v-else-if="error">{{ error.message }}</div>
<div v-else>{{ JSON.stringify(data) }}</div>
</div>
</template>
说明:
onError
用于处理特定错误,如 401 未授权。- 全局错误处理已在
alovaInstance
中配置。
7. 高级场景:请求队列与防抖
Alova 支持请求队列和防抖,优化高频请求场景。例如,搜索输入防抖:
<script setup>
import { ref } from 'vue';
import { useDebounce } from 'alova/client';
import { alovaInstance } from './alova';
const search = ref('');
// 定义搜索请求
const searchTodos = () => alovaInstance.Get('/todos', {
params: { search: search.value },
cacheFor: 0
});
// 使用防抖
const { loading, data } = useDebounce(searchTodos, [search], {
debounce: 500, // 500ms 防抖
initialData: []
});
</script>
<template>
<div>
<input v-model="search" placeholder="搜索待办事项" />
<div v-if="loading">加载中...</div>
<ul v-else>
<li v-for="todo in data" :key="todo.id">{{ todo.title }}</li>
</ul>
</div>
</template>
说明:
useDebounce
确保高频输入(如搜索)不会频繁触发请求。
Alova 的优势与适用场景
与其他库的对比
相比于 @tanstack/vue-query
或 swr
:
- 更集中的 API 管理:通过
Method
实例统一管理请求,减少代码分散。 - 内置业务策略:支持分页、表单、文件上传等场景,开箱即用。
- 与 Vue 3 的深度集成:响应式状态与 Composition API 完美结合。
- 轻量级:核心库体积小,性能开销低。
适用场景
- 复杂前端应用:如管理系统、电商平台,需管理大量 API。
- 动态交互场景:分页、搜索、表单提交等,Alova 的策略可大幅减少代码量。
- 性能敏感项目:通过缓存和请求共享,优化网络性能。
- 团队协作:统一的
Method
实例便于多人维护和 API 文档对接。
进阶技巧
1. 自定义请求策略
通过 useHookToSend
自定义 Hook,支持复杂业务逻辑。例如,创建一个带重试的请求:
import { useHookToSend } from 'alova/vue';
const useRetryRequest = (method, maxRetries = 3) => {
const { loading, data, error, send } = useHookToSend(method);
let retries = 0;
const retrySend = async () => {
try {
return await send();
} catch (err) {
if (retries < maxRetries) {
retries++;
return retrySend();
}
throw err;
}
};
return { loading, data, error, send: retrySend };
};
使用:
<script setup>
import { alovaInstance } from './alova';
const todoGetter = alovaInstance.Get('/todos/1');
const { loading, data, send } = useRetryRequest(todoGetter);
</script>
2. 状态持久化
Alova 支持将状态持久化到本地存储(如 localStorage),适合离线场景:
const todoListGetter = alovaInstance.Get('/todos', {
localCache: {
mode: 'storage',
expire: 1000 * 60 * 60 // 缓存 1 小时
}
});
3. 结合 DevTools
Alova 提供 DevTools 插件,可在浏览器中查看请求详情、缓存状态和 API 文档。安装方式:
npm install @alova/devtools
在 alova.js
中启用:
import { installAlovaDevtools } from '@alova/devtools';
installAlovaDevtools(alovaInstance);
开始使用 Alova
学习资源
- 官方文档:访问 alova.js.org 获取详细教程。
- GitHub:查看 alova 源码和示例。
- 社区:加入 GitHub Discussions 或 Discord,与开发者交流。
总结
Alova 通过声明式请求、响应式状态管理和内置策略,极大简化了 Vue 3 项目中的 API 交互。无论是简单的数据获取,还是复杂的分页、表单提交和文件上传,Alova 都能提供高效、优雅的解决方案。它的轻量级设计和 TypeScript 支持使其在现代前端开发中独具优势。