create-adaptable-composable

create-adaptable-composable

热门

创建库级别的 Vue composable,支持接收兼具响应性的入参(MaybeRef / MaybeRefOrGetter),方便调用方传入普通值、ref 或 getter。在响应式副作用(watch / watchEffect)内部利用 toValue() / toRef() 规范化入参,保障调用的可预测性与响应力。当用户需要创建灵活适配、高复用的 composable 时使用本 Skill。

2749Star
157Fork
更新于 2026/5/30
SKILL.md
只读
名称
create-adaptable-composable
描述

创建库级别的 Vue composable,支持接收兼具响应性的入参(MaybeRef / MaybeRefOrGetter),方便调用方传入普通值、ref 或 getter。在响应式副作用(watch / watchEffect)内部利用 toValue() / toRef() 规范化入参,保障调用的可预测性与响应力。当用户需要创建灵活适配、高复用的 composable 时使用本 Skill。

创建高适配度的 Composable

高适配性的 composable(组合式函数)是指能够同时接收响应式与非响应式入参的可复用函数。这使得开发者在各种场景下使用该 composable 时,无需担心入参是否具备响应性。

在 Vue.js 中设计高适配性 composable 的步骤:

  1. 明确该 composable 的功能职责、API 设计以及预期的输入/输出。
  2. 识别哪些入参需要具备响应性支持(选用 MaybeRef 或 MaybeRefOrGetter)。
  3. 在响应式副作用内部,使用 toValue()toRef() 对入参进行规范化解包。
  4. 结合 Vue 的响应式 API 实现 composable 的核心逻辑。

核心类型概念

类型工具函数

/**
 * 普通值或可写 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);

规范与原则

  • 只读、对计算属性友好的入参:使用 MaybeRefOrGetter
  • 需要支持可写 / 双向绑定的入参:使用 MaybeRef
  • 入参本身可能就是函数值(如回调函数/谓词函数/比较器):不要使用 MaybeRefOrGetter,否则可能会误将其当作 getter 函数执行。
  • DOM/元素节点目标:如果希望支持计算属性/衍生出来的节点,使用 MaybeRefOrGetter

当使用 MaybeRefOrGetterMaybeRef 时:

  • 需要获取响应式引用时,使用 toRef() 处理(例如作为侦听器 watcher 的数据源)
  • 需要提取纯值时,使用 toValue() 处理

代码示例

支持灵活适配的 useDocumentTitle Composable:接收只读的 title 参数

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:接收支持双向读写的 count 参数

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 }
}