create-adaptable-composable

create-adaptable-composable

熱門

建立套件庫等級的 Vue Composable,使其支援可為響應式的輸入(MaybeRef / MaybeRefOrGetter),讓呼叫者無論傳入純值、Ref 或 Getter 都能彈性處理。在響應式副作用(watch / watchEffect)內部透過 `toValue()` / `toRef()` 正規化輸入,確保行為具備可預測性與響應性。當使用者要求建立具高適應性或可複用的 Composable 時,請使用此 Skill。

2749星標
157分支
更新於 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(值/ref/shallowRef/可寫入的 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
  • 參數可能是函式值(回呼函式 callback / 斷言 predicate / 比較器 comparator):請勿使用 MaybeRefOrGetter,否則可能會誤將其當成 Getter 執行。
  • DOM / Element 目標:若需要支援計算或衍生出來的目標,請使用 MaybeRefOrGetter

當使用 MaybeRefOrGetterMaybeRef 時:

  • 解析響應式數值時使用 toRef()(例如作為偵聽器來源 watcher source)
  • 解析非響應式數值時使用 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 }
}