MST
星途 面试题库

面试题:Vue中ref与reactive在深层对象响应式更新的实现差异

假设你有一个多层嵌套的对象,使用ref和reactive分别对其进行响应式声明。当你修改深层对象的某个属性值时,Vue是如何检测到变化并更新视图的?两者在检测机制和性能优化方面有何不同?请结合Vue的响应式原理详细说明。
41.4万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

使用ref声明多层嵌套对象及变化检测

  1. 声明:使用ref声明多层嵌套对象时,ref会将传入的值包裹成一个带有.value属性的对象。例如:
import { ref } from 'vue';
const nestedObject = ref({
  a: {
    b: {
      c: 1
    }
  }
});
  1. 变化检测:当修改深层对象属性时,如nestedObject.value.a.b.c = 2,由于ref包裹的对象本身是一个响应式引用,Vue通过Object.definePropertygettersetter来追踪对.value的访问和修改。当.value被修改,Vue能够检测到引用的变化,进而触发视图更新。因为整个nestedObject.value被视为一个整体,任何对其内部属性的更改都会导致整个对象引用的变化检测。

使用reactive声明多层嵌套对象及变化检测

  1. 声明:使用reactive声明多层嵌套对象时,reactive会直接将传入的对象转换为响应式对象。例如:
import { reactive } from 'vue';
const nestedObject = reactive({
  a: {
    b: {
      c: 1
    }
  }
});
  1. 变化检测:Vue利用Object.defineProperty对对象的每个属性进行劫持,为每个属性设置gettersetter。当访问或修改深层对象属性nestedObject.a.b.c = 2时,setter会被触发,Vue的依赖收集机制能够检测到该属性的变化,并通知相关的Watcher进行视图更新。Vue会精准地检测到具体属性的变化,而不是像ref那样基于整个对象引用的变化。

检测机制不同点

  • ref:基于对象引用的变化检测,修改深层属性时,因为整体对象引用通过.value被修改,从而触发更新。它是对整个值的包裹,检测粒度相对较粗。
  • reactive:基于对对象每个属性的劫持,通过gettersetter精准检测到具体属性的变化,检测粒度更细。

性能优化不同点

  • ref:由于是基于对象引用变化,当深层属性变化时,可能会导致不必要的重新渲染,因为整个对象引用变化会使Vue认为整个对象都改变了,即便只是深层的一个小属性改变。但在一些简单场景或者对性能要求不高的场景下,使用简单,代码逻辑清晰。
  • reactive:因为能精准检测到具体属性变化,在大型复杂对象且频繁修改深层属性的场景下,性能更优。Vue可以只针对变化的属性进行更新,减少不必要的重新渲染。但在嵌套层级过深时,依赖收集和更新的开销也会增大,需要合理设计数据结构来优化。