跳到主要内容
版本:v3

结合UI框架

接下来,我们将学习如何与客户端的 UI 框架结合使用,这可以让 alova 发挥出真正的力量,在 UI 框架中使用时,不仅可以让 alova 自动管理响应式的请求状态,还能通过一定规则自动控制什么时候应该发送请求。

alova中提供了 10+个客户端的请求策略,它们帮助你以简单优雅的用法实现复杂的请求,让我们继续往下看吧!

设置 statesHook

在使用请求策略前,我们需要在 alova 实例上设置对应的 statesHook,它必须和项目使用的 UI 框架对应,这非常重要,它将告诉 alova 应该创建对应 UI 框架的响应式状态,目前支持以下框架:

import { createAlova } from 'alova';
import VueHook from 'alova/vue';

export const alovaInstance = createAlova({
// ...
statesHook: VueHook
});

自动管理请求状态

useRequest是我们最常用的请求策略,它可以帮我们创建和维护请求的响应式状态,如loading/data/error等,你可以直接在视图中使用这些响应式状态,当它们更改时,视图也将随之变化。

useRequest 表示一次请求的发送,调用时默认将发送一次请求。

<template>
  <div v-if="loading">Loading...</div>
  <div v-else-if="error">{{ error.message }}</div>
  <div v-else>
    <div>请求结果: {{ data }}</div>
    <button @click="handleSend">手动发送请求</button>
    <button @click="handleUpdate">手动修改data</button>
  </div>
</template>

<script setup>
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.value = { title: 'new title' };
};
</script>

何时使用 useRequest ,何时通过await alovaInstance.Get 发送请求

useHook 使用规范

请注意,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的基础使用,其他常用的请求策略还有:

  1. useWatcher: 监听数据变化并自动请求
  2. useForm: 表单数据数据提交与管理
  3. useAutoRequest: 按定时轮询、浏览器聚焦、网络重连等规则自动请求
  4. ...

了解完整使用或其他客户端请求策略,请移步客户端策略查看 alova 提供的所有客户端请求策略。