shallowreadonly 是 vue 3 中创建浅层只读代理的 api,仅冻结对象第一层属性,内层嵌套对象仍可修改;适用于需部分保护、性能敏感或第三方数据封装等场景。

shallowReadonly 是 Vue 3 中用于创建“浅层只读”代理的响应式 API,它只冻结对象最外层属性,内部嵌套对象仍可自由修改。
核心行为:只锁一层,不递归
与 readonly 不同,shallowReadonly 不会遍历并冻结所有嵌套层级。它仅拦截对第一层属性的赋值操作,而内层对象、数组或 ref 的值保持可写。
- 修改顶层属性(如 name、id)会失败,并在开发模式下触发警告
- 修改深层属性(如 user.profile.avatar 或 list[0].title)完全允许,且能正常触发视图更新(前提是原对象本身是响应式的)
- 返回的是一个 Proxy 对象,可通过 isReadonly() 判断其只读状态;但 isReadonly(obj.nested) 返回 false
典型适用场景
它解决的是“部分保护、部分放开”的实际需求,常见于以下情况:
使用 `@ainative/vue-sdk` 为 Vue 3 应用添加 AI 聊天功能。适用于以下场景:(1) 安装 `@ainative/vue-sdk`,(2) 在 Vue 组件中使用 `useChat` 组合式函数,(3) 提供……
- 接收父组件传入的配置对象:父组件希望子组件只读使用 apiUrl、timeout 等基础字段,但允许子组件动态更新 loading 状态或 error 信息
- 封装第三方数据源:比如从后端获取的用户基本信息(id、username)需锁定,但地址、偏好等子对象可能由本地表单实时编辑
- 性能敏感的大对象:当对象结构深、字段多时,用 readonly 会造成大量 Proxy 嵌套和依赖追踪开销;shallowReadonly 避免了这部分成本
使用注意事项
它不是万能锁,用错反而引发隐性 bug:
- 不能替代数据校验逻辑——它只在运行时拦截赋值,不阻止业务代码中通过方法间接修改内层
- 避免嵌套使用:不要对 shallowReadonly 的结果再套 reactive 或 readonly,会导致响应行为不一致
- 与 ref 搭配需谨慎:shallowReadonly 包裹的 ref 对象,其 .value 属性本身不可赋新值,但 .value 内部若为普通对象,其属性仍可改
简单对比 readonly
两者都返回只读代理,但冻结深度不同:
- readonly(obj) → 整棵树只读:obj.name = 'x' ❌,obj.info.city = 'y' ❌
- shallowReadonly(obj) → 仅根层只读:obj.name = 'x' ❌,obj.info.city = 'y' ✅
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










