likes
comments
collection
share

还在用axios发送请求?来看看alova的高阶用法!alova 提供了基础的,与 axios 相似的基础请求能力,你可

作者站长头像
站长
· 阅读数 20

0. 什么是alova

alova 提供了基础的,与 axios 相似的基础请求能力,你可以配合 axios、fetch 等任何请求库使用,获得响应缓存请求共享跨组件刷新等开箱即用的特性

注意 本文档内容是以alova@2.x为基础进行介绍,目前alova@3.x版本已经发布,如果你打算使用新版本的话,请注意二者 之间的API差异

1.缓存策略

alova会按照请求的路径、参数、method等自动创建缓存key,然后对请求数据进行缓存,加快接口的响应,同时避免不必要的接口请求,降低对服务端的压力。 alova提供3种不同的缓存策略:

1.1 内存模式

内存缓存模式是将响应数据存放在内存中,缓存在刷新页面即失效。

export const queryStudentDetail = (id) =>
  alovaInst.Get(`/student/${id}`, {
    // set the timestamp of memery cache
    localCache: 10 * 60 * 60,
  });

localCache默认为内存模式,因此我们只需要设置缓存时间即可。

1.2 占位模式

缓存占位模式是将响应数据持久化,它将在刷新页面后立即更新到 data state 中作为占位数据,同时发送请求,开发者可以在响应前使用占位数据替代 Loading 状态。

export const queryRandom = () =>
  alovaInst.Get('/query-random', {
    localCache: {
      mode: 'placeholder',
      expire: 10 * 60 * 60,
    },
  });

占位模式会优先返回本地缓存的数据,同时在发起请求,获得响应数据后进行替换。这种模式可以让用户先看到数据,比起看loading状态的体验好得多。

1.3 恢复模式

export const queryRandom = () =>
  alovaInst.Get('/query-random', {
    localCache: {
      mode: 'restore',
      expire: 10 * 60 * 60,
    },
  });

缓存恢复模式是将响应数据持久化,当请求命中缓存时将持久化缓存数据返回,不再发出请求。它一般用于一些需要服务端管理,但在一定时间内不变的数据。

恢复模式常用于一些数据变化很少变化或基本上不会变化的数据,例如节假日数据、城市数据等一些基础数据。

特别注意,这里的expire除了可以设置为一个相对时间以外,也可以设置为一个绝对时间Date类型,例如我们假设今年的节假日数据在1月1日之前都不变化,则可以将expire设置为new Date('2025-01-01 00:00:00')

那万一我的数据就是发生了变化,然后又被前端给使用恢复模式缓存了,应该如何处理,这种情况我们可以给alova的方法增加一个tag属性,来标识缓存key值,从而让已缓存的数据失效,重新从接口获取。

export const queryHolidays = () =>
  alovaInst.Get('/query-holidays', {
    localCache: {
      mode: 'restore',
      expire: 10 * 60 * 60,
      tag: 'v1.1'
    },
  });

2.当成store来用

了解了alova的缓存模式以后,对于一些页面组件间的共享数据来说,你就可以把alova当成一个微型的store来使用:

import { queryHolidays } from './api.js';
import { useRequest } from 'alova';

const {
  loading,
  error,
  data: holidays,
} = useRequest(queryHolidays);

虽然这看起来并没有什么特别之处,但是却极大的减少了开发时对于store和hooks的依赖。

想想,如果按照常规的做法,你需要先创建一个store,可能还需要定义一些对应的getters/actions,或者创建一个hooks来对数据的缓存进行维护。而且类似的数据越来越多的时候,你就会发现,你的这些store或者hooks的功能都十分的雷同,无法就是查询缓存,请求接口,设置缓存,格式化数据...现在这些都可以被alova给完成了。

3.加载更多

使用分页策略,实现更加高性能易用的分页功能,分页相关状态自动管理、前后一页预加载、自动维护数据的新增/编辑/替换/移除,以及请求级的防抖功能。

  1. 初始化完成后会预加载下一页数据,下拉翻页无需等待;
  2. 添加、删除、修改列表项无需重置列表,它将自动处理成和重新请求一致的效果;
import { queryStudents } from "./api.js";
import { usePagination } from "@alova/scene-vue";

const {
  loading,
  data: students,
  isLastPage,
  page,
  pageSize,
  remove,
  insert,
  refresh,
  reload,
  update,
  replace,
} = usePagination(
  (page, pageSize) =>
    queryStudents(page, pageSize, studentName.value || "", clsName.value || ""),
  {
    watchingStates: [studentName, clsName],
    append: true,
    initialData: [],
    data: r => r,
    debounce: [500],
  }
);

usePagination一旦将append设置为true之后,将会变身为加载更多的模式,同时它还提供了完整一套关于加载更多列表的操作:

  1. 返回了dataloadingisLastPageisLastPagerefreshreload等属性和方法,直接配置一个加载更多的UI组件,我们很快就能完成一个加载更多的列表开发
  2. 对于isLastPage的计算,pageCount 有值时会通过 pageCount 和 page 对比得到,否则会通过列表数据长度是否少于 pagSize 得到
  3. 对于列表数据提供了完整的insertremoveupdatereplace操作,借助这些方法,我们可以直接在列表上完成对数据的CRUD操作;
  4. 借助watchingStates属性配置,可以完成对字段的变化监听,然后自动发起请求,因此我们可以完成列表过滤、搜索、筛选等常规功能;watchingStates默认监听了pagepageSize属性,对于用作分页数据查询也十分有效;
  5. preloadPreviousPagepreloadNextPage默认自动加载当前页的相邻页数据,加快在切换分页或加载更多时数据的响应。

4.缓存自动失效方案

在上面,我们已经见识了alova强大的缓存策略和加载更多方案,但是同时也会带来一个问题: 如何主动让缓存失效

方法1:使用alova的invalidateCache手动将单个方法或者全部缓存失效

方法2:自动失效:对于一些关联性特别明显的接口,这个方法这个简洁,也更加符合接口整体逻辑的设计。例如我们有一个todo列表接口,有一个发布todo的接口,很明显,我发布todo以后,列表的本地缓存就应该失效,重新获取,否则用户就需要一直等待直到失效时间到期。

const getTodos = () => {
  alova.Get('/todos', {  
    // 匹配method实例名称为submitTodo的失效源  
    hitSource: 'submitTodo'  
  });
}

const submitTodo = (data) => {
    alova.Post('/todo', data, {  
        name: 'submitTodo'  
    });
}

我们定义了两个alova接口,一个获取todo列表,一个提交todo,当submitTodo提交成功后,将自动触发getTodos的缓存失效,再次请求时将从服务端获取数据。

5.跨组件触发请求

从前,在一个组件中想要触发另一个组件中的请求,你需要将数据保存到 Store 中,通过分发 Action 完成。现在,你可以使用这个中间件消除组件层级的限制,在任意组件中快速地触发任意请求的操作函数。

例如,你可以某个组件中更新了菜单数据后,重新触发侧边菜单栏的重新请求,从而刷新数据。当操作了列表数据后,触发列表更新。

组件A:使用actionDelegationMiddleware进行委托操作:

import { actionDelegationMiddleware } from '@alova/scene-vue';

useRequest(queryTodo, {
  middleware: actionDelegationMiddleware('actionName')
});

完成委托后,在其他任意组件中,我们可以通过accessAction传入指定的委托名称触发组件 A 中的useRequest的操作函数

import { accessAction } from '@alova/scene-vue';

accessAction('actionName', delegatedActions => {
  // 调用组件A中的send函数
  delegatedActions.send();

  // 调用组件A中的abort函数
  delegatedActions.abort();
});

至此,我们就摆脱store或组件层层传递的困扰,轻松完成跨组件的请求触发。

转载自:https://juejin.cn/post/7399954302217093156
评论
请登录