在组合式函数中封装 computed 逻辑,需将其与依赖的响应式状态一同创建和暴露,确保语义清晰、外部不可意外修改;支持参数化配置、避免副作用、强化类型安全与只读保护。

在组合式函数中封装可复用的 computed 逻辑,关键在于把它和相关响应式状态一起提取、统一管理,并确保返回值语义清晰、外部不可意外修改。
把 computed 和依赖状态打包返回
不要单独导出一个 computed,而是让它和它所依赖的 ref 一起被创建、一起被暴露。这样调用方拿到的是完整、自洽的一组响应式数据。
- 例如封装一个带格式化的用户名显示逻辑:
import { ref, computed } from 'vue'export function useFormattedUser(rawName = '') { const name = ref(rawName) const displayName = computed(() => { return name.value ? `@${name.value.trim()}` : '未命名' }) return { name, displayName }}
-
displayName是只读的计算属性,外部无法赋值;name是可写的 ref,供组件控制原始值 - 调用时直接解构使用:
const { name, displayName } = useFormattedUser('alice')
支持参数化与配置化
当计算逻辑需要灵活行为(比如不同前缀、大小写策略),可通过选项对象传入配置,让 computed 基于这些配置动态响应。
立即学习“前端免费学习笔记(深入)”;
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
- 示例:可配置的标题格式器
interface UseTitleOptions { prefix?: string uppercase?: boolean}export function useTitle(text: Ref<string>, options: UseTitleOptions = {}) {</string> const { prefix = '', uppercase = false } = options const formatted = computed(() => { let result = text.value if (prefix) result = `${prefix} ${result}` if (uppercase) result = result.toUpperCase() return result }) return { formatted }}
- 接收
Ref<string></string>而非原始字符串,保证响应性穿透 - 配置项在 setup 中可响应式更新,
computed会自动重新求值
避免副作用,保持纯响应式
computed 函数体内不应有副作用(如发请求、修改其他 ref、触发事件)。它只负责声明“如何从已有响应式数据派生新值”。
- ❌ 错误:在
computed里调用api.getUser()—— 这属于异步逻辑,应交给watch或独立方法 - ✅ 正确:用
computed处理格式转换、条件拼接、数组过滤(不触发网络)等纯同步派生 - 若需“根据某值变化自动执行动作”,应搭配
watch或封装成方法(如refresh()),而非塞进computed
类型安全与只读保护
用 readonly() 包裹 computed 返回值,防止调用方误写;配合 TypeScript 接口明确返回结构。
- 增强类型提示:
import { ref, computed, readonly, type ComputedRef } from 'vue'interface UseCounterReturn { count: ComputedRef<number></number> isEven: ComputedRef<boolean></boolean>}export function useCounter(initial = 0) { const count = ref(initial) const isEven = computed(() => count.value % 2 === 0) return { count: readonly(count), isEven: readonly(isEven), // 显式只读,更安全 } as const satisfies UseCounterReturn}

















