vue3 响应式 API:readonly() 与 shallowReadonly()
readonly()
readonly()
是一个用于创建只读代理对象的函数。它接受一个对象 (不论是响应式还是普通的) 或是一个 ref,返回一个原值的只读代理。
类型
function readonly<T extends object>(target: T
): DeepReadonly<UnwrapNestedRefs<T>>
以下是对这个函数签名的详细解释:
- 参数
target: T
:target
是要被转换为只读对象的输入对象。T extends object
表示类型参数T
必须是一个对象类型,这确保了输入的target
只能是对象而不是基本数据类型(如数字、字符串等)。
- 返回值
DeepReadonly<UnwrapNestedRefs<T>>
:这个函数返回一个深度只读的、解包了嵌套响应式对象的新对象。DeepReadonly
是一个工具类型,它使传入的类型变为深度只读类型,即对象的所有嵌套属性也都是只读的。UnwrapNestedRefs
是一个工具类型,它用于解包嵌套的响应式对象(由ref
或reactive
创建的对象),将嵌套的响应式对象转换为普通的 JavaScript 对象。
示例
readonly()
创建的只读代理是深层的:对任何嵌套属性的访问都将是只读的。它的 ref
解包行为与 reactive()
相同,但解包得到的值是只读的。
- 对象的所有嵌套属性都将变为只读。
- 任何尝试修改这个对象的操作都会被阻止(在开发模式下,还会在控制台中发出警告)。
import { readonly } from 'vue';
let readonlyObj = readonly({message: 'hello',info: {name: 'readonly',back: 'Proxy对象'}
})// 报错:无法为“message”赋值,因为它是只读属性。
readonlyObj.message = 'hello'
// 无法为“name”赋值,因为它是只读属性。
readonlyObj.info.name = 'readonly!'
如果原始对象是响应式的,那么通过readonly
创建的对象也会保持响应性:原始对象的属性发生变化,只读对象也会反映这些变化。
import { reactive, readonly } from 'vue';let reactiveObj = reactive({message: 'hello'
})let readonlyObj = readonly(reactiveObj)
console.log(reactiveObj, readonlyObj)// 修改原始对象reactiveObj
reactiveObj.message = 'hello, world!'
console.log(reactiveObj, readonlyObj)
查看控制台打印结果:
只读对象readonlyObj
跟随原始对象reactiveObj
的变化而变化。
应用场景
- 创建不可变的状态快照。
- 保护全局状态或配置不被修改。
shallowReadonly()
shallowReadonly()
是 readonly()
的浅层作用形式,是一个用于创建浅层只读代理对象的函数。
shallowReadonly
接受一个对象作为参数,并返回一个新的代理对象。
shallowReadonly
创建的对象是浅层只读的:
- 只将对象的顶层属性设置为只读,对象内部的嵌套属性可以被修改。
- 适用于只需保护对象顶层属性的场景。
import { reactive, shallowReadonly } from 'vue';let readonlyObj = shallowReadonly({message: 'hello',info: {name: 'readonly',back: 'Proxy对象'}
})// 无法为“message”赋值,因为它是只读属性。
readonlyObj.message = 'hello, world!'
// name是嵌套属性,不是readonlyObj的第一层属性,因此,name可以被修改
readonlyObj.info.name = 'readonly!!!'
如果原始对象是响应式的,那么通过shallowReadonly
创建的对象也会保持响应性。