alova是一个轻量级的请求策略库,旨在简化接口的管理和使用。它分为两部分:
-
声明式实现复杂请求: 支持开发者使用声明式方法实现复杂请求,如请求共享、分页请求、表单提交、断点续传等,无需编写大量代码,提高开发效率,应用性能,减轻服务端压力。
-
API自动管理和维护: 可生成完整的、描述详尽的请求函数的TypeScript类型,使前端项目与服务器端无缝对接,无需查阅API文档,获得类型提示。当服务端API更新时,前端项目会收到通知并阻止项目发布。
使用alovajs后,你只需要选择对应的useHook进行请求即可,被称为懒人版请求库。如果你也喜欢 alovajs,请在Github 仓库中贡献一颗 star,这对我们非常重要。
欢迎加入交流社区
有任何使用问题,你可以加入以下群聊咨询,也可以在github 仓库中发布 Discussions,如果遇到问题,也请在github 的 issues中提交,我们会在最快的时间解决。
同时也欢迎贡献你的一份力量,请移步贡献指南。
以下为部分章节的教程,想学习更多 alovajs 的用法,欢迎来alova 官网学习。
在alova
中提供了useRequest
、useWatcher
、useFetcher
三种 use hook 实现请求时机,由它们控制何时应该发出请求,同时将会为我们创建和维护状态化的请求相关数据,如loading
、data
、error
等,无需自主维护这些状态,下面我们来了解下它们。
本次我们先了解第一个 use hook,useRequest ,它表示一次请求的发送,执行useRequest
时默认会发送一次请求,在页面获取初始数据时是最常用的方法,同时也支持关闭它的默认的请求发送,这在提交数据等通过点击事件触发的请求场景非常有用。
初始数据请求
我们来为 todo 列表获取页面数据。
vue
html
<template>
<!-- 你可以直接使用 data 来渲染 todo 列表 -->
<div v-if="loading">Loading...</div>
<div
v-else-if="error"
class="error">
{{ error.message }}
</div>
<template v-else>
<div v-for="todo in data">
<div class="todo-title">{{ todo.title }}</div>
<div class="todo-time">{{ todo.time }}</div>
</div>
</template>
</template>
<script setup>
const {
// loading是加载状态值,当加载时它的值为true,结束后自动更新为false
// 它是一个Ref类型的值,你可以通过loading.value访问它,或直接绑定到界面中
loading,
// 响应数据,同样是Ref值
data,
// 请求错误对象,Ref值,请求错误时有值,否则为undefined
error
// 直接将Method实例传入即可发送请求
} = useRequest(todoListGetter, {
// 请求响应前,data的初始值
initialData: []
});
</script>
react
jsx
const App = () => {
const {
// loading是加载状态值,当加载时它的值为true,结束后自动更新为false
// 它的值为普通的boolean值,请求状态变化时内部将自动调用set函数更新它的值
loading,
// 响应数据
data,
// 请求错误对象,请求错误时有值,否则为undefined
error
// 直接将Method实例传入即可发送请求
} = useRequest(todoListGetter, {
// 请求响应前,data的初始值
initialData: []
});
// 你可以直接使用 todoList 来渲染 todo 列表
if (loading) {
return <div>Loading...</div>;
} else if (error) {
return <div class="error">{error.message}</div>;
} else {
return (
<>
<div v-for="todo in data">
<div class="todo-title">{todo.title}</div>
<div class="todo-time">{todo.time}</div>
</div>
</>
);
}
};
svelte
html
<script>
const {
// loading是加载状态值,当加载时它的值为true,结束后自动更新为false
// 它是一个Writable类型的值,内部将维护它
loading,
// 响应数据
data,
// 请求错误对象,请求错误时有值,否则为undefined
error
// 直接将Method实例传入即可发送请求
} = useRequest(todoListGetter, {
// 请求响应前,data的初始值
initialData: []
});
</script>
<!-- 你可以直接使用 todoList 来渲染 todo 列表 -->
{#if $loading}
<div>Loading...</div>
{:else if $error}
<div class="error">{ $error.message }</div>
{:else} {#each $data as todo}
<div>
<div class="todo-title">{ todo.title }</div>
<div class="todo-time">{ todo.time }</div>
</div>
{/each} {/if}
绑定请求回调
如需设置请求回调,你还可以在 useRequest 的返回参数中接收回调的设置函数,如下:
javascript
const {
// ...
// 成功回调绑定
onSuccess,
// 失败回调绑定
onError,
// 完成回调绑定,回调在成功或失败都会调用
onComplete
} = useRequest(todoListGetter);
onSuccess(event => {
console.log('请求成功,响应数据为:', event.data);
console.log('本次请求的method实例为:', event.method);
console.log('响应数据是否来自缓存:', event.fromCache);
});
onError(event => {
console.log('请求失败,错误信息为:', event.error);
console.log('本次请求的method实例为:', event.method);
});
onComplete(event => {
// event.status在成功时为success,失败时为error
console.log('请求完成,状态为:', event.status);
console.log('本次请求的method实例为:', event.method);
console.log('响应数据是否来自缓存:', event.fromCache);
if (event.data) {
console.log('请求数据:',event.data)
} else if (event.error) {
console.log('错误信息:',event.error)
}
});
在
onSuccess
中抛出错误将会触发onError
手动发送请求
当你需要创建一条新的 todo 项时,可以先关闭默认发送请求,转为手动触发请求,并在 useRequest 中接收send
函数用于手动发送请求,send
函数将返回带响应数据的 Promise 实例,它将在请求响应后改为 resolve 状态。
javascript
const {
// ...
// 手动发送器请求的函数,调用后发送请求
send: addTodo
} = useRequest(newTodo => alovaInstance.Post('/todo', newTodo), {
// 当immediate为false时,默认不发出
immediate: false
});
// 手动发送请求
const handleAddTodo = () => {
const newTodo = {
title: '新的todo项',
time: new Date().toLocaleString()
};
// send函数返回一个Promise对象,可接收响应数据
addTodo(newTodo)
.then(result => {
console.log('新增todo项成功,响应数据为:', result);
})
.catch(error => {
console.log('新增todo项失败,错误信息为:', error);
});
};
[2.9.0+]
在 react 中,send 函数使用了useCallback
包裹,同时它也不受闭包陷阱限制,你可以直接在事件中使用它,不用担心引起性能问题。
强制发送请求
缓存数据可以很好地提升应用流畅性和减小服务端压力,但同时也存在着数据过期的问题,当你希望穿透缓存获取最新数据时,在 use hooks 的配置中设置force
属性可以帮助你。
设置静态值
force 默认为 false,设置为 true 时将每次穿透缓存,并发送请求
javascript
useRequest(alovaInstance.Get('/todo'), {
force: true
});
动态设置 force 值
实际情况中,我们经常需要根据不同情况来设置是否需要强制发送请求,此时可以将 force 设置为一个函数,此函数可通过 send 函数传入。
javascript
const { send } = useRequest(alovaInstance.Get('/todo'), {
force: id => {
return !!id;
}
});
send(1);
send 函数参数传递规则
在上面的示例中,调用 send 函数手动触发请求,它可以接受任意多个参数,这些参数将分别被以下 5 个函数接收:
在 useRequest 回调函数中接收
当 useRequest 的第一个参数设置为回调函数时可以接收到,这通常在删除列表项时很有用,具体如下:
javascript
const { send } = useRequest(id => removeTodoPoster(id));
send(1); // 上面回调函数中的id将接收到1
在 onSuccess、onError、onComplete 回调函数中接收
onSuccess、onError、onComplete 回调函数中的event.sendArgs
以数组形式接收
javascript
const { send, onSuccess, onError, onComplete } = useRequest(newTodo => alovaInstance.Post('/todo', newTodo));
onSuccess(event => {
// sendArgs的值为[1]
console.log(event.sendArgs);
});
onError(event => {
// sendArgs的值为[1]
console.log(event.sendArgs);
});
onComplete(event => {
// sendArgs的值为[1]
console.log(event.sendArgs);
});
// 发送请求
send(1);
在 force 函数中接收
javascript
const { send } = useRequest(alovaInstance.Get('/todo'), {
force: id => {
return !!id;
}
});
send(1);
设置初始响应数据
一个页面在获取到初始数据前,不可避免地需要等待服务端响应,在响应前一般需要先将状态初始化为一个空数组或空对象,以免造成页面报错,我们可以在useRequest
中的第二个参数实现初始数据的设置。
javascript
// 在useRequest中设置初始数据
const {
// 响应前data的初始值为[],而不是undefined
// highlight-start
data
} = useRequest(todoListGetter, {
initialData: []
});
// highlight-end
手动修改状态值
在 alova 中,通过useRequest
返回的data
、loading
、error
等各项状态是允许自定义修改的,这在一些情况下将变得很方便。
vue
javascript
const { data, loading, error, update } = useRequest(todoListGetter);
// ...
// 直接修改data值
data.value = {};
// 或者通过update函数修改
update({
data: {}
});
react
在 react 中,返回的状态是直接可使用的数据,因此需通过update
函数来修改。
javascript
const { data, loading, error, update } = useRequest(todoListGetter);
// ...
// 通过update修改data值
update({
data: {}
});
svelte
在 svelte 中,useRequest
返回的状态为writable
类型。
javascript
const { data, loading, error, update } = useRequest(todoListGetter);
// ...
// 直接修改data值
$data = {};
// 或data.update(d => ({}));
// 或者通过update函数修改
update({
data: {}
});
注意事项
- 自定义修改的值将会被
useRequest
内部的状态管理机制覆盖,如当你修改了data
值,再次请求后data
值将被赋值为最新的响应数据; - 通过直接修改的状态值不会同步修改缓存数据,如需要同步修改缓存数据,建议使用updateState
:::
手动中断请求
未设置timeout
参数时请求是永不超时的,如果需要手动中断请求,可以在useRequest
函数被调用时接收abort
方法。
javascript
const {
// ...
// highlight-start
// abort函数用于中断请求
abort
// highlight-end
} = useRequest(todoListGetter);
// highlight-start
// 调用abort即可中断请求
const handleCancel = () => {
abort();
};
// highlight-end
[2.9.0+]
在 react 中,abort 函数使用了useCallback
包裹,同时它也不受闭包陷阱限制,你可以直接在事件中使用它,不用担心引起性能问题。
[2.6.2+]
另外,这个abort
函数也会同时绑定到当前的 method 实例上,因此你也可以这样来中断请求。
javascript
useRequest(todoListGetter);
// highlight-start
// 调用method上的abort也可以中断当前请求
const handleCancel = () => {
todoListGetter.abort();
};
// highlight-end
[2.6.2+]
你还可以在beforeRequest
中调用abort
中断请求。
javascript
const alovaInst = createAlova({
// ...
beforeRequest(method) {
if (someCondition) {
method.abort();
}
}
});
为什么要使用alova
alova 也致力于解决客户端网络请求的问题,但与其他请求库不同的是,alova 选择了业务场景化请求策略的方向,它配合axios/fetch api
等请求库后能满足你绝大部分请求需求(99%)的同时,还提供了丰富的高级功能。
- 你可能曾经也在思考着应该封装
fetch
和axios
,现在你不再需要这么做了,通过 alova 使用声明的方式完成请求,例如请求共享、分页请求、表单提交、断点上传等各种较复杂的请求,以及自动化缓存管理、请求共享、跨组件更新状态等。 - alova 是轻量级的,只有 4kb+,是 axios 的 30%+。
- 目前支持
vue/react/react-native/svelte
,以及next/nuxt/sveltekit
等 SSR 框架,同时也支持Uniapp/Taro
多端统一框架。 - alova 是低耦合的,你可以通过不同的适配器让 alova 在任何 js 环境下,与任何 UI 框架协作使用(内置支持的 UI 框架为
vue/react/svelte
),并且提供了统一的使用体验和完美的代码迁移。 - 使用 alova 还能实现 api 代码的高聚合组织方式,每个 api 的请求参数、缓存行为、响应数据转换等都将聚集在相同的代码块中,这对于管理大量的 api 有很大的优势。
多框架支持
现在,你还可以在 vue options(vue2 和 vue3) 写法中完美使用 alova,点此查看详情。后续我们将陆续支持以下框架:
- 函数式,如
solid/preact/qwik
。 - class 式,如
angular/lit/stencil
。 - options 式,如
原生小程序(中国🇨🇳)
。
alovajs 还提供了其他强大的请求策略:
名称 | 描述 | 文档 |
---|---|---|
分页请求策略 | 自动管理分页数据,数据预加载,减少不必要的数据刷新,流畅性提高 300%,编码难度降低 50% | usePagination |
无感数据交互策略 | 全新的交互体验,提交即响应,大幅降低网络波动造成的影响,让你的应用在网络不稳定,甚至断网状态下依然可用 | useSQRequest |
表单提交策略 | 为表单提交而设计的 hook,通过此 hook 你可以很方便地实现表单草稿、多页面(多步骤)表单,除此以外还提供了表单重置等常用功能 | useForm |
文件上传策略 | 更简单的文件上传策略,支持对 base64、Blob、ArrayBuffer、Canvas 数据的自动识别和转换 | useUploader |
发送验证码 | 验证码发送 hook,减掉你在开发验证码发送功能时的繁琐。 | useCaptcha |
自动重新拉取数据 | 在一定条件下自动重新拉取数据,保证始终展示最新数据。 | useAutoRequest |
跨组件触发请求 | 一个 alova 中间件,消除组件层级的限制,在任意组件中快速地触发任意请求的操作函数 | actionDelegationMiddleware |
串行请求的 useRequest | 比alova 的串行请求方式更加简洁易用的串行请求 use hook,提供统一的 loading 状态、error、回调函数 | useSerialRequest |
串行请求的 useWatcher | 比alova 的串行请求方式更加简洁易用的串行请求 use hook,提供统一的 loading 状态、error、回调函数。 | useSerialWatcher |
请求重试策略 | 请求失败自动重试,它在重要的请求和轮询请求上发挥重要作用 | useRetriableRequest |
SSE 请求 | 通过 Server-sent Events 进行请求 | useSSE |
想学习更多 alovajs 的用法,欢迎来alova 官网学习。如果你也喜欢 alovajs,请在Github 仓库中贡献一颗 star,这对我们非常重要。
如果觉得文章对你有帮助,请别吝啬你的赞和评论哈,说说你对 alovajs 怎么看的,或者可以问一些问题,我会尽量回答的,你的支持是我创作的最大动力!哈哈哈哈哈哈~
欢迎加入交流社区
有任何问题,你可以加入以下群聊咨询,也可以在github 仓库中发布 Discussions,如果遇到问题,也请在github 的 issues中提交,我们会在最快的时间解决。
同时也欢迎贡献你的一份力量,请移步贡献指南。