组合式函数中封装 ref 的三种方式:一是用 readonly 包裹实现只读暴露;二是仅返回 getter/setter 彻底隐藏 ref;三是用 computed 包装实现派生与防护,均旨在保障私有状态隔离与数据安全。

在组合式函数中用 ref 返回私有状态,核心是让 ref 变量不暴露给调用方,只通过返回的函数或计算属性间接控制其读写,从而实现封装和数据隔离。
封装 ref 为只读访问
使用 readonly 包裹 ref,阻止外部直接修改,同时允许读取:
- 调用方只能访问
.value,但无法赋值(尝试赋值会静默失败或报开发警告) - 内部仍可通过原 ref 修改,保持逻辑可控
- 适合需要对外暴露当前值、但不允许随意篡改的场景
示例:
import { ref, readonly } from 'vue'<br><br>export function useCounter() {<br> const count = ref(0)<br><br> const increment = () => count.value++<br> const reset = () => count.value = 0<br><br> // 返回只读副本 + 操作方法<br> return {<br> count: readonly(count),<br> increment,<br> reset<br> }<br>}
完全隐藏 ref,仅暴露 getter/setter
不返回 ref 本身,而是返回普通函数,由内部 ref 承载状态:
- 调用方完全感知不到 ref 的存在,更彻底地隔离实现细节
- getter 返回当前值,setter 封装赋值逻辑(可加校验、日志等)
- 适用于高内聚、需强约束的状态管理
示例:
import { ref } from 'vue'<br><br>export function useAuthToken() {<br> const token = ref('')<br><br> return {<br> getToken() { return token.value },<br> setToken(newToken) {<br> if (typeof newToken === 'string') {<br> token.value = newToken.trim()<br> }<br> },<br> clearToken() { token.value = '' }<br> }<br>}
结合 computed 实现派生与防护
用 computed 包装 ref,对外提供带逻辑的响应式视图:
- computed getter 可做格式化、过滤、默认值兜底等处理
- 若需可写,可配对使用
computed({ get, set }),set 中再操作原始 ref - 既保护源数据,又增强接口语义
示例(只读格式化):
import { ref, computed } from 'vue'<br><br>export function useUserName() {<br> const rawName = ref('')<br><br> return {<br> // 外部看到的是首字母大写的版本<br> displayName: computed(() => {<br> const n = rawName.value.trim()<br> return n ? n[0].toUpperCase() + n.slice(1) : 'Anonymous'<br> }),<br> updateName(name) { rawName.value = name }<br> }<br>}
注意:避免意外泄露响应式引用
以下写法会破坏封装性,应避免:
- 直接返回
count(即 ref 对象本身),调用方可任意修改.value - 解构返回对象时丢失响应性(如
const { count } = useCounter()后再传入其他函数)——虽 ref 本身不失效,但已脱离组合函数上下文约束 - 将 ref 赋给全局变量或跨组件共享,违背“私有”初衷
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










