Vue.js 3 - Composition API使用详解3(readonly、isProxy、isReactive、isReadonly、toRaw函数)
作者:hangge | 2026-04-27 08:42
三、readonly、isProxy、isReactive、isReadonly、toRaw、shallowReactive、shallowReadonly 函数
1,readonly 函数
(1)通过 reactive 或 ref 函数可以获取一个响应式对象。这些响应式对象都是可以被更改的,但是在某些情况下,我们希望响应式对象只读且不能更改。比如,当我们在向其他组件传递数据时,希望其他子组件在使用该内容时不允许修改。
(2)这时可以使用 Vue.js3 提供的 readonly 函数。该函数会返回原生对象的只读代理对象,该对象的 setter 方法被劫持了,不允许对其进行修改。readonly 函数通常可接收以下三种类型的参数:
- 普通对象。
- reactive 函数返回的响应式对象。
- ref 函数返回的响应式对象。
(3)readonly 函数在使用时,有如下规则:
- readonly 返回的对象都是不允许被修改的。但是,经过 readonly 处理的原来的对象是允许被修改的。比如,在 const info=readonly(obj)中,info 对象是不允许被修改的, obj 是可以被修改的。当 obj 被修改时,readonly 返回的 info 对象也会被修改。但是,我们不能修改 readonly 返回的 info 对象,否则会报错。
- readonly 函数的本质是该函数返回代理对象的 setter 方法被劫持了,不允许对其进行修改。
(4)下面演示 readonly 函数使用,我们在 setup 函数中分别演示了 readonly 函数接收三种不同类型的参数,用于返回原生对象的只读代理。该对象只能读,不能被修改。
<template>
<div>
<button @click="updateState">修改状态</button>
</div>
</template>
<script>
import { reactive, ref, readonly } from 'vue';
export default {
setup() {
// 1.类型一:普通对象
const info1 = { name: "航歌" };
const readonlyInfo1 = readonly(info1);
// 2.类型二:响应式的对象reactive
const info2 = reactive({
name: "航歌"
})
const readonlyInfo2 = readonly(info2);
// 3.类型三:响应式的对象ref
const info3 = ref("航歌");
const readonlyInfo3 = readonly(info3);
// 点击修改状态
const updateState = () => {
readonlyInfo1.name = "hangge" // 只读,修改会报警告
// info1.name = "hangge"; // 可修改
readonlyInfo2.name = "hangge" // 只读,修改会报警告
// info2.name = "hangge";// 可修改
readonlyInfo3.value = "hangge" // 只读,修改会报警告
// info3.value = "hangge";// 可修改
}
return {
updateState,
}
}
}
</script>
(5)运行效果如下,可以看到如果修改只读 readonlyInfol、readonlyInfo2 和 readonlyInfo3 对象,在浏览器的控制台会出现“Set operation on key"name"failed:target is readonly”的警告。

2,isProxy 函数
(1)isProxy 函数可以检查对象是否为由 Vue.js3 中的 reactive 或 readonly 创建的 Proxy 对象。
- 需要注意的是,ref 创建的是 Reflmpl 对象,因此 isProxy 函数不能用于检查对象是否为 ref。
(2)下面时一个简单的使用样例:
import { readonly, isProxy } from 'vue';
const original = { name: 'Alice' };
const ro = readonly(original);
console.log(isProxy(ro)); // true
console.log(isProxy(original)); // false(普通对象不是 Proxy)
3,isReactive 函数
(1)isReactive 函数可以检查对象是否为由 reactive 创建的响应式代理对象,注意:
- 如果代理对象是由 readonly 函数创建的,并且参数为 reactive 创建的响应式对象,那么也会返回 true。
- 但如果 readonly 包装的是普通对象,不是 reactiv 创建的响应式对象,那么就会返回 false。
import { reactive, readonly, isReactive } from 'vue';
const state = reactive({ count: 0 });
const ro1 = readonly(state);
const obj = { name: 'hangge' };
const ro2 = readonly(obj);
console.log(isReactive(state)); // true
console.log(isReactive(ro1)); // true(内部仍是 reactive)
console.log(isReactive(ro2)); // false(readonly不会把普通对象转为reactive,它只是创建一个只读代理)
4,isReadonly 函数
(1)isReadonly 函数可以用于检查一个对象是否为由 readonly 创建的只读代理对象。
(2)下面是一个简单的样例:
import { readonly, isReadonly } from 'vue';
const original = { name: 'hangge' };
const ro = readonly(original);
console.log(isReadonly(ro)); // true
console.log(isReadonly(original)); // false(普通对象)
5,toRaw 函数
(1)toRaw 函数可以返回 reactive 或 readonly 代理对象的原始对象。
(2)下面是一个简单的样例:
import { readonly, toRaw } from 'vue';
const original = { msg: 'hello' };
const rt= reactive(original);
const ro = readonly(original);
console.log(toRaw(rt) === original); // true
console.log(toRaw(ro) === original); // true
6,shallowReactive 函数
(1)shallowReactive 函数可以创建一个浅层响应式代理对象,该对象只有根级别的属性是响应式的。由于没有进行深层级的转换,该对象深层嵌套的属性仍然是普通对象。
(2)下面是一个简单的使用样例:
const state = shallowReactive({
count: 0,
name: "hangge",
info: {
age: 99,
}
});
// 改变state的浅层属性是响应式的
state.count++;
// 深度嵌套的info对象不是响应式对象
isReactive(state.info); // false
state.info.age++; // 非响应式
7,shallowReadonly 函数
(1)shallowReadonly 函数可以创建一个浅层只读代理对象,该对象只有根级别的属性变为只读。因为没有进行深层级的转换,该对象深层嵌套的属性依然是可读可写的。
(2)下面是一个简单的使用样例:
const state = shallowReadonly({
count: 0,
name: "hangge",
info: {
age: 99,
}
});
// 改变state的浅层属性将失败
state.count++;
// 深度嵌套的info对象不是只读代理对象
isReactive(state.info); // false
state.info.age++; // 深层嵌套的info对象依然可读可写
全部评论(0)