结合UI框架
接下来,我们将学习如何与客户端的 UI 框架结合使用,这可以让 alova 发挥出真正的力量,在 UI 框架中使用时,不仅可以让 alova 自动管理响应式的请求状态,还能通过一定规则自动控制什么时候应该发送请求。
alova
中提供了 10+个客户端的请求策略,它们帮助你以简单优雅的用法实现复杂的请求,让我们继续往下看吧!
设置 statesHook
在使用请求策略前,我们需要在 alova 实例上设置对应的 statesHook,它必须和项目使用的 UI 框架对应,这非常重要,它将告诉 alova 应该创建对应 UI 框架的响应式状态,目前支持以下框架:
- vue
- react
- svelte
import { createAlova } from 'alova';
import VueHook from 'alova/vue';
export const alovaInstance = createAlova({
// ...
statesHook: VueHook
});
import { createAlova } from 'alova';
import ReactHook from 'alova/react';
export const alovaInstance = createAlova({
// ...
statesHook: ReactHook
});
import { createAlova } from 'alova';
import SvelteHook from 'alova/svelte';
export const alovaInstance = createAlova({
// ...
statesHook: SvelteHook
});
自动管理请求状态
useRequest
是我们最常用的请求策略,它可以帮我们创建和维护请求的响应式状态,如loading/data/error
等,你可以直接在视图中使用这些响应式状态,当它们更改时,视图也将随之变化。
useRequest 表示一次请求的发送,调用时默认将发送一次请求。
- vue
- react
- svelte
<script>
import { useRequest } from 'alova/client';
import { alovaInstance } from './api';
// 使用alova实例创建method并传给useRequest即可发送请求
const { loading, data, error, send, update, onSuccess } = useRequest(
alovaInstance.Get('/todos/1', {
cacheFor: 0
}),
{
initialData: {}, // 设置data状态的初始数据
immediate: true // 是否立即发送请求,默认为true
}
);
onSuccess(event => {
event.method; // 当前请求的method
event.data; // 当前请求的响应数据
});
const handleSend = () => {
send();
};
const handleUpdate = () => {
update({
data: { title: 'new title' }
});
// 也可以直接修改data值
// $data = { title: 'new title' };
// data.update(d => ({ title: 'new title' }));
}
</script>
{#if $loading}
<div>Loading...</div>
{:else if $error}
<div>{ $error.message }</div>
{:else}
<div>
<div>请求结果: {{ data }}</div>
<button on:click={handleSend}>手动发送请求</button>
<button on:click={handleUpdate}>手动修改data</button>
</div>
{/if}
何时使用 useRequest ,何时通过await alovaInstance.Get
发送请求。
请注意,useRequest
只能用于组件内发送请求,在组件外,你可以通过 method 实例直接发送请求,并且 useRequest
的使用需要符合 use hook 使用规则,即只能在函数最外层调用。
❌❌❌ 不推荐在在循环 、条件判断或者子函数中调用,例如以下在 click 回调中的使用示例,在回调函数中使用时,虽然可以正常发起请求,但 use hook 返回的响应式数据无法在视图中使用,循环和条件判断中使用也是如此。
// ❌ bad
const handleClick = () => {
const { loading, data } = useRequest(getter);
};
// -------
// ✅ good
const { loading, data, send } = useRequest(getter, {
immediate: false
});
const handleClick = () => {
send();
};
提交数据
当你需要提交一条新的 todo 项时,可以先关闭默认发送请求,转为手动触发请求,并在 useRequest 中接收send
函数用于手动发送请求,send
函数将返回带响应数据的 Promise 实例,它将在请求响应后改为 resolve 状态。
此时为了接收send
函数传入参数,可以将useRequest
的第一个参数设置为函数,我们称这个函数为 method handler。
const {
// ...
// 手动发送器请求的函数,调用后发送请求
send: addTodo
// 在这边将会接收到 send 函数的参数
} = 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);
});
};
send
函数可以让你自由地重复发起请求。
在 react 中,send 函数使用了
useCallback
包裹,同时它也不受闭包陷阱限制,你可以直接在事件中使用它,不用担心引起性能问题。
处理响应
请求完成后,响应数据会经过多个流程的处理,最终才会在发送请求的位置获得最终数据,流程如下:
当没有抛出错误时,下一个节点会接收到上一个节点的返回值。
转换响应数据
在method 详解中,我们已经了解过transform
了,这在 useHook 中使用也非常有用,它可以让 useHook 的 data 接收到转换后的数据,而不用再转换。
const todoListGetter = alovaInstance.Get('/todo/list', {
// 函数接受未加工的数据和响应头对象,并要求将转换后的数据返回,它将会被赋值给data状态。
// 注意:rawData是全局响应拦截器(如果有设置)过滤后的数据,响应拦截器的配置可以参考[设置全局响应拦截器]章节。
transform(rawData, headers) {
return rawData.list.map(item => ({
...item,
statusText: item.done ? '已完成' : '进行中'
});
}
});
const { data } = useRequest(todoListGetter);
data 值将接收到转换后的数据格式。
type data = {
// ...
statusText: '已完成' | '进行中';
}[];
在 usehooks 中使用时,在transform
中抛出错误也会触发onError
;
绑定响应回调
如需设置请求回调,你还可以在 useHooks 的返回参数中接收回调的设置函数,如下:
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)
}
});
我们在所有的 useHooks 中都支持了绑定函数的链式调用方式。
const { data, loading, error, onSuccess, onError, onComplete } = useRequest(todoListGetter)
.onSuccess(event => {
// ...
})
.onError(event => {
// ...
})
.onComplete(event => {
// ...
});
在onSuccess
中抛出错误将会触发onError
。
结尾
以上是我们最常用的useRequest
的基础使用,其他常用的请求策略还有:
- useWatcher: 监听数据变化并自动请求
- useForm: 表单数据数据提交与管理
- useAutoRequest: 按定时轮询、浏 览器聚焦、网络重连等规则自动请求
- ...
了解完整使用或其他客户端请求策略,请移步客户端策略查看 alova 提供的所有客户端请求策略。