79.Options Object 模式

有许多模式可以用来改进你的组合式函数(composables)。 使用对象来传递参数是一种非常有用的模式,在很多地方都有使用 --- 只需看看 VueUse 的源码就知道了。 但是,虽然这种模式乍看起来很简单,在实现时还是有一些需要考虑的事项:

  • 当你有很多选项时会发生什么?真的很多?

  • 当你只有几个选项时该怎么办?

  • 如何判断你是否在错误地使用这种模式?

在本文中,我们将探讨 Options Object 模式。我们将介绍实现的基础知识,然后转向高级用例以及权衡使用它时的利弊。

该模式如何工作

为了使我们的代码更具可重用性,我们需要它能覆盖广泛的情况。 我们通过传入一个包含所有配置选项的对象来实现这一点,这些选项决定了我们希望组合式函数如何表现:

go 复制代码
const state = ref({ email: '' });

const { history, undo, redo } = useRefHistory(state, {
  // 递归跟踪历史
  deep: true,
  // 限制我们保存的变更数量
  capacity: 10,
});

我们在这里使用对象而不是一长串参数:

go 复制代码
const { history, undo, redo } = useRefHistory(state, true, 10));

使用选项对象而不是参数给我们带来了几个好处。

首先,它是自文档化的。我们在值旁边直接有参数的名称,所以我们永远不会忘记每个值的作用。 我们还可以为整个选项对象创建一个类型:

go 复制代码
export type RefHistoryOptions {
  deep?: boolean;
  capacity?: number;
};

export type RefHistoryReturn {
  history: Ref;
  undo: () => void;
  redo: () => void;
};

export function useRefHistory(
  ref: Ref,
  options: RefHistoryOptions
): RefHistoryReturn {};

其次,我们不需要担心顺序或未使用的选项。我们用组合式函数覆盖的潜在边缘情况越多,就会有越多的选项。但我们通常只需要一次关注其中的几个 --- 它们都是可选的。

第三,添加新选项变得更加容易。因为顺序无关紧要,并且没有任何选项是必需的,所以向我们的组合式函数添加新功能不会破坏任何东西。我们只需将它添加到可能的选项列表中并继续前进。

实现该模式

实现这个模式也不需要太多工作:

go 复制代码
export function useRefHistory(ref, options) {
  const {
    deep = false,
    capacity = Infinity,
  } = options;

  // ...
};

首先,我们将选项对象作为最后一个参数传入。这使得选项对象本身成为一个可选参数成为可能。

必需的参数排在前面。通常,只会有一两个。更多的参数是代码异味,很可能意味着你的组合式函数试图做太多事情。

必需的参数(或参数们)通常是一个 Ref,或者如果我们也在实现灵活参数模式,则是一个 MaybeRef。