从 Axios 到 alova:一个页面从 80 行到 5 行的故事

前端开发中,请求状态管理一直是代码量的主要来源。本文以分页列表为切入点,对比纯 Axios 和 alova 两种实现方式,分析请求策略化模式在减少样板代码方面的效果与适用边界。


典型场景:分页列表的两种实现

先看一个最常见的需求:从后端获取用户列表,支持分页。

方案一:基于 Axios 的常规实现

javascript 复制代码
const [data, setData] = useState([]);
const [page, setPage] = useState(1);
const [pageSize] = useState(10);
const [total, setTotal] = useState(0);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);

const fetchUsers = async (currentPage) => {
  setLoading(true);
  setError(null);
  try {
    const res = await axios.get('/api/users', {
      params: { page: currentPage, pageSize: 10 },
    });
    setData(res.data.list);
    setTotal(res.data.total);
  } catch (e) {
    setError(e.message);
  } finally {
    setLoading(false);
  }
};

useEffect(() => { fetchUsers(page); }, [page]);

// 翻页处理
const handlePageChange = (newPage) => { setPage(newPage); };

这段代码包含了 5 个 state 声明、1 个 useEffect、1 个 try/catch 和 1 个翻页函数。核心业务逻辑------GET /api/users?page=1&pageSize=10------仅占了其中一行。

方案二:基于 alova 的 usePagination

javascript 复制代码
const {
  data, total, loading, error,
  page, pageSize, nextPage, prevPage,
} = usePagination(
  (page, pageSize) => alovaInstance.Get('/api/users', {
    params: { page, pageSize },
  }),
  { page: 1, pageSize: 10 }
);

两种写法的功能完全等价,但代码量从约 30 行(即使省略了翻页 UI 渲染部分)下降到 6 行。


差异分析:被减少的代码去了哪里?

对比两份代码,第一版中消失的部分是:

原 Axios 版本的组成 alova 中的处理方式
loading 状态声明 + 开关 usePagination 内部自动管理
error 状态声明 + 捕获 usePagination 内部自动捕获
data 状态声明 + 赋值 hook 返回值直接提供
page 状态 + 翻页函数 hook 返回值内置 nextPage / prevPage
total 状态 hook 自动从响应中提取
useEffect 依赖管理 hook 内部处理

这些被移除的代码有一个共同特征:它们属于请求场景的"通用基础设施",与具体业务无关。在传统方案中,这些基础设施在每个组件中都需要重新声明一次,形成了高比例的样板代码。

alova 的做法本质上是一种场景封装:将"分页请求"这个完整模式------包括数据获取、状态管理、翻页控制------整体抽象为一个声明式 hook。开发者只需描述"请求什么"和"初始参数",其余由 hook 接管。


扩展到其他请求场景

alova 的策略 hook 覆盖了前端开发中常见的请求模式:

useRequest --- 基础请求

javascript 复制代码
// 组件挂载时自动请求
const { data, loading, error } = useRequest(getUserList());

// 手动触发:点击按钮后发送
const { send } = useRequest(createOrder, { immediate: false });

useWatcher --- 响应式请求

javascript 复制代码
// keyword 变化时自动重新请求,内置防抖
const { data } = useWatcher(
  () => searchApi(keyword.value),
  [keyword],
  { debounce: 300 }
);

useForm --- 表单提交

javascript 复制代码
const {
  form, loading,
  send: submit,
  reset,
} = useForm(submitApi, {
  initialForm: { name: '', email: '' },
});

每个 hook 的返回值结构是统一的------都包含 dataloadingerror------同时在统一接口之上提供场景专属的能力。

六个场景的代码量对比:

场景 Axios 代码行数 alova 代码行数 减少比例 使用的 Hook
分页列表 ~30 行 6 行 ~80% usePagination
搜索防抖 ~25 行 3 行 ~88% useWatcher
表单提交 ~30 行 3 行 ~90% useForm
轮询刷新 ~25 行 3 行 ~88% useAutoRequest
链式依赖 ~30 行 5 行 ~83% useSerialRequest
文件上传 ~35 行 8 行 ~77% useUploader

注:行数基于简化后的核心逻辑统计,不含 UI 渲染代码和 import 语句。


适用场景与局限

alova 适合的情况:

  • 项目中存在大量"页面加载 → 发起请求 → 展示数据"的常规页面
  • 需要统一管理请求状态的项目(loading、error、数据一致性)
  • 频繁使用分页、搜索防抖、表单提交等标准化交互模式
  • 希望减少团队内请求代码风格差异的项目

alova 可能不太适合的情况:

  • 项目规模较小,请求逻辑简单,引入额外依赖的收益有限
  • 已经深度使用了 React Query、SWR 等成熟方案的团队,迁移成本需重点评估
  • 对请求行为有高度定制需求,且与 hook 预设行为不匹配的场景
  • 非 React/Vue/Svelte 的框架生态(需确认支持的框架列表)

其他考量:

  • 学习成本:与直接使用 Axios 相比,需要理解"策略 hook"的概念和各个 hook 的行为差异
  • 调试透明度:hook 封装了状态管理,在出现非预期行为时,排查可能比直接操作 state 多一层抽象
  • 迁移方式 :alova 的 Method 创建 API(GetPost 等)与 Axios 高度相似,可以逐步引入,无需全量重写
javascript 复制代码
// 两者的 Method 创建语法几乎相同
axios.get('/api/users', { params: { page: 1 } });
alovaInstance.Get('/api/users', { params: { page: 1 } });

小结

从 Axios 到 alova,核心变化不在于"换了一个请求库",而在于将请求视为可被完整封装的场景单元,而非一个需要手动管理所有副作用的原子操作。这种抽象层次的提升,是代码量显著减少的根本原因。

对于正在使用传统请求方案的项目,alova 提供了一种减少请求样板代码的可选路径。是否采用,取决于项目的具体需求、团队已有的技术栈和迁移成本的综合权衡。

相关推荐
Master_Azur1 小时前
JavaEE之反射、注解、代理设计模式
后端
Cobyte1 小时前
15.响应式系统比对:链表在 Preact Signals 响应式系统中的应用
前端·javascript·vue.js
KaMeidebaby1 小时前
卡梅德生物技术快报|基因测序技术在 46,XY 性发育障碍变异筛查中的流程与数据分析
服务器·前端·数据库·人工智能·算法·数据挖掘·数据分析
算法印象派2 小时前
Rokid AI 眼镜远程协作应用"一线互联"开发实践:设备发现与 BLE 扫描
后端
m0_738120722 小时前
渗透测试基础——黑盒测试下的Web漏洞挖掘与利用解析(二)
服务器·前端·python·网络协议·安全·网络安全
weixin_429630262 小时前
3.50 WebARNav:边缘辅助视觉定位的移动Web AR室内导航
前端·ar
basketball6162 小时前
Go 语言从入门到进阶:5. 玩转Go函数
开发语言·后端·golang
yivifu2 小时前
CSS 自动级联编号有序列表完全指南
前端·css·c#·html·有序列表·级联编号