Skip to content

useMemoize

类别
导出体积
403 B
上次更改
4 months ago

缓存依赖于参数的函数结果,并保持其响应性。它还可以用于异步函数,并将重用现有的 promises 来避免同时获取相同的数据。

TIP

结果不会自动清除。如果你不再需要结果,请调用 clear(),或使用自己的缓存机制来避免内存泄漏。

使用方法

ts
import { useMemoize } from '@vueuse/core'

const getUser = useMemoize(
  async (userId: number): Promise<UserData> =>
    axios.get(`users/${userId}`).then(({ data }) => data),
)

const user1 = await getUser(1) // 请求 users/1
const user2 = await getUser(2) // 请求 users/2
// ...
const user1 = await getUser(1) // 从缓存中获取

// ...
const user1 = await getUser.load(1) // 请求 users/1

// ...
getUser.delete(1) // 删除用户1的缓存
getUser.clear() // 清除完整缓存
js
import { useMemoize } from '@vueuse/core'
const getUser = useMemoize(async (userId) =>
  axios.get(`users/${userId}`).then(({ data }) => data),
)
const user1 = await getUser(1) // 请求 users/1
const user2 = await getUser(2) // 请求 users/2
// ...
const user1 = await getUser(1) // 从缓存中获取
// ...
const user1 = await getUser.load(1) // 请求 users/1
// ...
getUser.delete(1) // 删除用户1的缓存
getUser.clear() // 清除完整缓存

结合 computedasyncComputed 可以实现响应性:

ts
const user1 = asyncComputed(() => getUser(1))
// ...
await getUser.load(1) // 也会更新 user1

解析缓存键

缓存的键由传递给函数的参数确定,并且默认情况下将使用 JSON.stringify 进行序列化。 这将使相等的对象接收相同的缓存键。如果你想自定义键,可以通过 getKey 传递。

ts
const getUser = useMemoize(
  async (userId: number, headers: AxiosRequestHeaders): Promise<UserData> =>
    axios.get(`users/${userId}`, { headers }).then(({ data }) => data),
  {
    // 仅使用 userId 获取/设置缓存,忽略 headers
    getKey: (userId, headers) => userId,
  },
)
js
const getUser = useMemoize(
  async (userId, headers) =>
    axios.get(`users/${userId}`, { headers }).then(({ data }) => data),
  {
    // 仅使用 userId 获取/设置缓存,忽略 headers
    getKey: (userId, headers) => userId,
  },
)

WARNING

对于 Vue 2,键必须是 stringnumber

自定义缓存机制

默认情况下,结果将缓存在 Map 中 (对于 Vue 2,则是普通对象)。你可以通过在选项中传递 cache 来实现自己的机制,具体如下:

ts
export interface MemoizeCache<Key, Value> {
  /**
   * 获取键的值
   */
  get: (key: Key) => Value | undefined
  /**
   * 为键设置值
   */
  set: (key: Key, value: Value) => void
  /**
   * 返回键是否存在的标志
   */
  has: (key: Key) => boolean
  /**
   * 删除键的值
   */
  delete: (key: Key) => void
  /**
   * 清除缓存
   */
  clear: () => void
}
js
export {}

类型声明

显示类型声明
typescript
type CacheKey = any
/**
 * 自定义记忆缓存处理程序
 */
export interface UseMemoizeCache<Key, Value> {
  /**
   * 获取键的值
   */
  get: (key: Key) => Value | undefined
  /**
   * 设置键的值
   */
  set: (key: Key, value: Value) => void
  /**
   * 返回键是否存在的标志
   */
  has: (key: Key) => boolean
  /**
   * 删除键的值
   */
  delete: (key: Key) => void
  /**
   * 清除缓存
   */
  clear: () => void
}
/**
 * 记忆化函数
 */
export interface UseMemoizeReturn<Result, Args extends unknown[]> {
  /**
   * 从缓存中获取结果或调用记忆化函数
   */
  (...args: Args): Result
  /**
   * 调用记忆化函数并更新缓存
   */
  load: (...args: Args) => Result
  /**
   * 删除给定参数的缓存
   */
  delete: (...args: Args) => void
  /**
   * 清除缓存
   */
  clear: () => void
  /**
   * 为给定参数生成缓存键
   */
  generateKey: (...args: Args) => CacheKey
  /**
   * 缓存容器
   */
  cache: UseMemoizeCache<CacheKey, Result>
}
export interface UseMemoizeOptions<Result, Args extends unknown[]> {
  getKey?: (...args: Args) => string | number
  cache?: UseMemoizeCache<CacheKey, Result>
}
/**
 * 基于参数的响应式函数结果缓存
 */
export declare function useMemoize<Result, Args extends unknown[]>(
  resolver: (...args: Args) => Result,
  options?: UseMemoizeOptions<Result, Args>,
): UseMemoizeReturn<Result, Args>

源码

源码文档

贡献者

Anthony Fu
一纸忘忧
Anthony Fu
Mikhailov Nikita
Jelf
freakzlike

更新日志

v10.8.0 on 2/20/2024
a086e - fix: stricter types
v10.7.0 on 12/5/2023
fecbe - fix: use shallowReactive to wrap Map