今天被问到一个问题:使用 Vue 3 中提供的 reactive 函数定义响应式对象并且希望某个深层属性不是响应式的该如何实现?

106 阅读2分钟
reactive 函数定义响应式对象并且希望某个深层属性不是响应式这个问题自己之前还真的没有去考虑过hhh,然后查了查有以下两种方式去解决这个问题:

一、 可以在创建时先将这个属性设置为普通对象,再在之后需要使用时再使用 reactive 方法进行转换。示例如下:

import {reactive} from 'vue';

const obj = reactive({
a: 1,
b: {
c: {
d: 2
}
},
e: null
});

// 将 b.c.d 设置为普通对象

obj.b.c.d = { value: 2 };

// 在需要使用时再将其转化为响应式对象

obj.b.c.d = reactive(obj.b.c.d);

这种做法的缺点是需要手动判断和处理哪些属性需要是响应式的,如果嵌套过于复杂或者数据结构层次太深,这样的处理可能会比较繁琐。

**二、**Vue 3 中还提供了另外一种方式可以控制属性的响应式状态,即使用 shallowReactiveshallowRef 函数。

shallowReactive 可以创建一个仅对对象的第一层进行响应式处理的 reactive 对象。这意味着对象的深层属性将不会是响应式的。示例如下:

import { shallowReactive } from 'vue';

const obj = shallowReactive({
  a: 1,
  b: {
    c: {
      d: 2
    }
  },
  e: null
});

// b.c.d 不是响应式的
console.log(obj.b.c.d); // { value: 2 }

如果要使用响应式的 b.c.d 属性,可以使用 shallowRef 函数将其转化为响应式对象。示例如下:

import { shallowRef } from 'vue';

obj.b.c.d = shallowRef(obj.b.c.d);

// 现在 b.c.d 是响应式的了
console.log(obj.b.c.d.value); // 2

这样做的好处是可以更方便地控制对象的响应式范围,避免了手动判断和处理哪些属性需要是响应式的情况。如果你只想让对象的某一层或多层是响应式的,可以使用 shallowReactive 并使用 shallowRef 将需要响应式的属性转化为响应式对象。