在 Vue 3 中,readonly 和 shallowReadonly 是两个用于创建只读响应式代理的实用函数。它们的主要目的是为了防止意外修改对象的属性,但它们在实现这一点上有不同的方式。
readonly
readonly 函数创建一个只读的响应式代理对象。这意味着你不能直接修改对象的属性,但如果你修改对象内部的嵌套属性,仍然会导致响应式系统的更新。
用途
- 完全只读:当你希望整个对象及其所有嵌套属性都变为只读时。
- 防止意外修改:当你希望确保没有人能直接修改对象时。
示例
import { reactive, readonly } from 'vue';
const state = reactive({
count: 0,
details: { name: 'Alice' }
});
const stateReadOnly = readonly(state);
// 试图修改顶层属性会失败
stateReadOnly.count = 10; // TypeError: Cannot assign to read only property 'count'
// 试图修改嵌套属性也会失败
stateReadOnly.details.name = 'Bob'; // TypeError: Cannot assign to read only property 'name'
shallowReadonly
shallowReadonly 函数创建一个只读的响应式代理对象,但只针对顶层属性。这意味着你可以修改嵌套对象的属性,而不会触发错误。
用途
- 部分只读:当你只想保护顶层属性不被修改时。
- 性能优化:当嵌套对象很大或包含许多嵌套层次时,使用
shallowReadonly可以避免代理这些对象,从而提高性能。
示例
import { reactive, shallowReadonly } from 'vue';
const state = reactive({
count: 0,
details: { name: 'Alice' }
});
const stateShallowReadOnly = shallowReadonly(state);
// 试图修改顶层属性会失败
stateShallowReadOnly.count = 10; // TypeError: Cannot assign to read only property 'count'
// 但是可以修改嵌套属性
stateShallowReadOnly.details.name = 'Bob'; // 成功修改
比较
readonly:创建一个完全只读的响应式代理对象,包括所有的嵌套属性。shallowReadonly:创建一个只读的响应式代理对象,但只对顶层属性进行只读处理,嵌套属性仍然可以修改。
何时使用
- 当你需要保护整个对象及其所有嵌套属性时,使用
readonly。 - 当你只需要保护顶层属性,而嵌套属性可以自由修改时,使用
shallowReadonly。
总结
readonly 和 shallowReadonly 都是为了创建只读的响应式代理对象。readonly 会保护整个对象及其所有嵌套属性,而 shallowReadonly 只保护顶层属性。根据你的具体需求选择合适的函数来保护对象或提高性能。