返回 导航

Vue.js

hangge.com

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)通过 reactiveref 函数可以获取一个响应式对象。这些响应式对象都是可以被更改的,但是在某些情况下,我们希望响应式对象只读且不能更改。比如,当我们在向其他组件传递数据时,希望其他子组件在使用该内容时不允许修改。 

(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)运行效果如下,可以看到如果修改只读 readonlyInfolreadonlyInfo2readonlyInfo3 对象,在浏览器的控制台会出现“Set operation on key"name"failed:target is readonly”的警告。 

2,isProxy 函数

(1)isProxy 函数可以检查对象是否为由 Vue.js3 中的 reactivereadonly 创建的 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

(2)下面是一个简单的使用样例:
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 函数可以返回 reactivereadonly 代理对象的原始对象。 

(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)

回到顶部