create-agnostic-composable

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Create Agnostic Composable

创建通用型Composable

Agnostic composables are reusable functions that can accept both reactive and non-reactive inputs. This allows developers to use the composable in a variety of contexts without worrying about the reactivity of the inputs.
Steps to design an agnostic composable in Vue.js:
  1. Confirm the composable's purpose and API design and expected inputs/outputs.
  2. Identify inputs params that should be reactive (MaybeRef / MaybeRefOrGetter).
  3. Use
    toValue()
    or
    toRef()
    to normalize inputs inside reactive effects.
  4. Implement the core logic of the composable using Vue's reactivity APIs.
通用型composable是可复用的函数,能够同时接收响应式和非响应式输入。这让开发者可以在各种场景下使用该composable,无需担心输入的响应式问题。
在Vue.js中设计通用型composable的步骤:
  1. 确认composable的用途、API设计以及预期的输入/输出。
  2. 识别需要支持响应式的输入参数(MaybeRef / MaybeRefOrGetter)。
  3. 在响应式副作用内部使用
    toValue()
    toRef()
    来标准化输入。
  4. 使用Vue的响应式API实现composable的核心逻辑。

Core Type Concepts

核心类型概念

Type Utilities

类型工具

ts
/**
 * value or writable ref (value/ref/shallowRef/writable computed)
 */
export type MaybeRef<T = any> = T | Ref<T> | ShallowRef<T> | WritableComputedRef<T>;

/**
 * MaybeRef<T> + ComputedRef<T> + () => T
 */
export type MaybeRefOrGetter<T = any> = MaybeRef<T> | ComputedRef<T> | (() => T);
ts
/**
 * value or writable ref (value/ref/shallowRef/writable computed)
 */
export type MaybeRef<T = any> = T | Ref<T> | ShallowRef<T> | WritableComputedRef<T>;

/**
 * MaybeRef<T> + ComputedRef<T> + () => T
 */
export type MaybeRefOrGetter<T = any> = MaybeRef<T> | ComputedRef<T> | (() => T);

Policy and Rules

原则与规则

  • Read-only, computed-friendly input: use
    MaybeRefOrGetter
  • Needs to be writable / two-way input: use
    MaybeRef
  • Parameter might be a function value (callback/predicate/comparator): do not use
    MaybeRefOrGetter
    , or you may accidentally invoke it as a getter.
  • DOM/Element targets: if you want computed/derived targets, use
    MaybeRefOrGetter
    .
When
MaybeRefOrGetter
or
MaybeRef
is used:
  • resolve reactive value using
    toRef()
    (e.g. watcher source)
  • resolve non-reactive value using
    toValue()
  • 只读、支持计算属性的输入:使用
    MaybeRefOrGetter
  • 需要支持可写/双向绑定的输入:使用
    MaybeRef
  • 参数可能是函数值(回调/断言/比较器):不要使用
    MaybeRefOrGetter
    ,否则可能会意外将其作为getter调用。
  • DOM/Element目标:如果需要支持计算/派生的目标,使用
    MaybeRefOrGetter
当使用
MaybeRefOrGetter
MaybeRef
时:
  • 使用
    toRef()
    解析响应式值(例如作为watcher的源)
  • 使用
    toValue()
    解析非响应式值

Examples

示例

Agnostic
useDocumentTitle
Composable: read-only title parameter
ts
import { watch, toRef } from 'vue'
import type { MaybeRefOrGetter } from 'vue'

export function useDocumentTitle(title: MaybeRefOrGetter<string>) {
  watch(toRef(title), (t) => {
    document.title = t
  }, { immediate: true })
}
Agnostic
useCounter
Composable: two-way writable count parameter
ts
import { watch, toRef } from 'vue'
import type { MaybeRef } from 'vue'

function useCounter(count: MaybeRef<number>) {
  const countRef = toRef(count)
  function add() {
    countRef.value++
  }
  return { add }
}
通用型
useDocumentTitle
Composable:只读标题参数
ts
import { watch, toRef } from 'vue'
import type { MaybeRefOrGetter } from 'vue'

export function useDocumentTitle(title: MaybeRefOrGetter<string>) {
  watch(toRef(title), (t) => {
    document.title = t
  }, { immediate: true })
}
通用型
useCounter
Composable:双向可写的计数参数
ts
import { watch, toRef } from 'vue'
import type { MaybeRef } from 'vue'

function useCounter(count: MaybeRef<number>) {
  const countRef = toRef(count)
  function add() {
    countRef.value++
  }
  return { add }
}