readonly() 可创建只读但响应式的代理,对 reactive/ref 对象生效,嵌套属性自动受保护;用于防止子组件误改父组件状态,配合 torefs、shallowreadonly、computed 更实用,但仅作用于响应式对象,生产环境静默忽略赋值。

直接用 readonly() 包一层响应式对象,就能得到一个只读但依然响应式的副本。它不改原始数据,只是加了一层“写入防护”。
怎么写:基础用法
传入 reactive 或 ref 创建的对象,返回只读代理:
- 对 ref 使用:
const readOnlyRef = readonly(myRef),之后readOnlyRef.value = xxx在开发环境会警告 - 对 reactive 使用:
const readOnlyObj = readonly(myReactiveObj),修改readOnlyObj.count或readOnlyObj.nested.prop都会触发警告 - 支持嵌套属性自动保护——改深层字段(如
obj.user.profile.level)同样被拦截
为什么需要它:解决常见误操作
尤其在父子组件通信中,避免子组件意外改父组件状态:
- 父组件用
defineProps接收数据后,直接传给子组件的 props 是可变的(Vue 只对顶层属性做浅警告) - 用
readonly(props)封装后再传递,连props.user.name = 'xxx'和props.user.profile.id = 123都会被拦截 - 比单纯靠开发规范更可靠,是代码层面的硬约束
搭配使用更实用
单独用 readonly 很简单,但常和其它 API 组合提升安全性或便利性:
-
配合 toRefs:先
readonly(reactive({ a: 1 })),再toRefs(...),解构出的每个 ref 仍保持只读语义 -
配合 shallowReadonly:如果只要第一层不可改(比如大型数组列表),用
shallowReadonly更轻量,深层仍可写 -
配合 computed:返回只读计算值,防止外部篡改缓存结果,例如
computed(() => readonly(state))
注意边界情况
它不是万能锁,几个关键点要清楚:
- 只对响应式对象起作用——普通对象用
readonly({})没有意义,也不会报错,但也不受保护 - 生产环境静默失败:开发时警告,上线后赋值操作直接忽略,不报错也不抛异常
- 不冻结原始对象:
readonly(obj)后,obj本身仍可自由修改,只读副本只是“视角隔离”
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










