返回

Vue3中shallowReactive和shallowRef对数据进行非深度监听

前端

Vue3 中 ref 和 reactive 都是深度监听

在 Vue3 中,ref 和 reactive 都是用来创建响应式数据的,但它们在底层实现上存在着一些差异。

  • ref 是通过 Object.defineProperty() 方法来创建的,它会将一个对象或者数组的每个属性都变成响应式的。
  • reactive 是通过 Proxy 对象来创建的,它会将整个对象或者数组都变成响应式的。

这意味着,如果我们使用 ref 来创建一个对象或者数组,那么对这个对象或者数组的任何属性进行更改,都会触发组件的重新渲染。

const obj = ref({
  name: 'John Doe',
  age: 30
});

obj.value.name = 'Jane Doe'; // 触发重新渲染

如果我们使用 reactive 来创建一个对象或者数组,那么对这个对象或者数组的任何属性进行更改,也会触发组件的重新渲染。

const obj = reactive({
  name: 'John Doe',
  age: 30
});

obj.name = 'Jane Doe'; // 触发重新渲染

说明 ref 对数据进行深度监听

当我们使用 ref 来监听一个对象或者数组时,这个对象或者数组的每个属性都会被标记为脏,从而触发组件的重新渲染。

const obj = ref({
  name: 'John Doe',
  age: 30,
  address: {
    street: '123 Main Street',
    city: 'Anytown',
    state: 'CA',
    zip: '12345'
  }
});

obj.value.address.street = '456 Elm Street'; // 触发重新渲染

在上面的例子中,当我们更改 obj.value.address.street 的值时,整个 obj 对象都会被标记为脏,从而触发组件的重新渲染。

使用 shallowReactive

为了只对某些属性进行监听,而不希望对整个对象或数组进行监听,可以使用 shallowReactive 来创建一个浅响应式对象或数组。

const obj = shallowReactive({
  name: 'John Doe',
  age: 30
});

obj.name = 'Jane Doe'; // 触发重新渲染
obj.age = 31; // 不触发重新渲染

在上面的例子中,当我们更改 obj.name 的值时,整个 obj 对象都会被标记为脏,从而触发组件的重新渲染。但是,当我们更改 obj.age 的值时,obj 对象不会被标记为脏,因此不会触发组件的重新渲染。

这是因为 shallowReactive 只会对对象的顶层属性进行监听,而不会对对象的嵌套属性进行监听。

const obj = shallowReactive({
  name: 'John Doe',
  age: 30,
  address: {
    street: '123 Main Street',
    city: 'Anytown',
    state: 'CA',
    zip: '12345'
  }
});

obj.address.street = '456 Elm Street'; // 不触发重新渲染

在上面的例子中,当我们更改 obj.address.street 的值时,obj 对象不会被标记为脏,因此不会触发组件的重新渲染。这是因为 shallowReactive 只会对对象的顶层属性进行监听,而不会对对象的嵌套属性进行监听。

使用 shallowRef

shallowRef 和 shallowReactive 类似,都是用来创建浅响应式数据,但 shallowRef 是用来创建浅响应式值,而 shallowReactive 是用来创建浅响应式对象或数组。

const name = shallowRef('John Doe');

name.value = 'Jane Doe'; // 触发重新渲染

在上面的例子中,当我们更改 name.value 的值时,name 对象会被标记为脏,从而触发组件的重新渲染。

但是,当我们使用 shallowRef 来创建一个嵌套对象或数组时,嵌套对象或数组的属性不会被标记为脏,因此不会触发组件的重新渲染。

const obj = shallowRef({
  name: 'John Doe',
  age: 30,
  address: {
    street: '123 Main Street',
    city: 'Anytown',
    state: 'CA',
    zip: '12345'
  }
});

obj.value.address.street = '456 Elm Street'; // 不触发重新渲染

在上面的例子中,当我们更改 obj.value.address.street 的值时,obj 对象不会被标记为脏,因此不会触发组件的重新渲染。这是因为 shallowRef 只会对值的顶层属性进行监听,而不会对值的嵌套属性进行监听。

总结

在 Vue3 中,shallowReactive 和 shallowRef 可以用来创建浅响应式数据。浅响应式数据只对顶层属性进行监听,而不会对嵌套属性进行监听。这可以减少组件的重新渲染次数,提高应用程序的性能。