vue为什么深度监听能监听到数据
-
Vue的深度监听能够监听到数据,是因为Vue使用了一种叫做响应式的机制来管理数据。在Vue中,使用了Object.defineProperty()方法来劫持对数据的访问,从而实现了数据的双向绑定和变化的追踪。
具体来说,当我们在Vue中声明一个数据对象时,Vue会通过遍历这个对象的属性,并使用Object.defineProperty()方法为每个属性生成一个getter和setter。这样,当我们访问这个属性时,Vue会通过getter来返回属性的值,而当我们修改这个属性时,Vue会通过setter来捕捉到修改操作,并及时更新相关的视图。
而深度监听就是在这个基础上进行了增强。当我们在数据对象中使用了嵌套对象或数组时,Vue会递归地对嵌套的对象或数组中的属性进行深度监听。这样一来,无论是修改了嵌套对象中的属性,还是对数组进行了增删改操作,Vue都能够捕捉到这些变化,并及时更新相关的视图。
实现深度监听的关键在于递归地监听嵌套对象和数组。当我们修改嵌套对象中的属性时,Vue会通过setter捕获这个修改操作,并对这个属性进行深度监听。同样地,当我们对数组进行了增删改操作时,Vue也会通过特定的方法例如push()、pop()、splice()等来捕获这些操作,并对整个数组进行深度监听。
通过深度监听,Vue能够实现数据的响应式更新,保证了数据和视图的同步更新。同时,深度监听也给我们提供了便利,使得在数据变化时能够迅速响应并做出相应的处理,提高了开发效率。
2年前 -
Vue.js 中的深度监听是通过使用
vm.$watch方法进行实现的。Vue.js 使用的是响应式系统来跟踪数据的变化,通过使用Object.defineProperty方法来劫持对象的属性,当属性发生变化时,会触发对应的响应式更新。在 Vue.js 中,当我们使用
vm.$watch方法进行深度监听时,实际上是在监听一个对象的所有属性的变化。当对象的属性发生变化时,就会触发对应的回调函数。以下是深度监听能监听到数据的几个原因:
-
引用类型数据的属性变化会触发响应式更新:当我们对一个对象的属性进行修改时,Vue.js 会自动检测到这个变化,然后触发对应的响应式更新。这意味着,无论对象的属性是在 Vue 实例创建之前还是之后添加的,只要是引用类型的属性发生了变化,都会被深度监听到。
-
对象的属性添加和删除也会触发响应式更新:当我们添加或删除一个对象的属性时,Vue.js 也会自动检测到这个变化并触发响应式更新。这意味着,不仅仅是属性值的变化,属性的添加和删除也会被深度监听到。
-
数组的变化也会触发响应式更新:Vue.js 中的数组也是经过特殊处理的。当我们通过数组的方法对数组进行修改时,Vue.js 会自动检测到这个变化并触发响应式更新。例如,当我们使用
push、pop、splice等方法对数组进行修改时,这个变化会被深度监听到。 -
对象和数组的嵌套结构也可以被深度监听:深度监听不仅限于一层对象或数组的变化,它可以递归地监听对象和数组的嵌套结构。例如,当对象的属性值是对象或数组时,对嵌套对象或数组的属性进行修改,同样会触发响应式更新。
-
深度监听是通过递归实现的:在 Vue.js 中,当我们使用
vm.$watch进行深度监听时,实际上是通过递归的方式实现的。Vue.js 会遍历对象的所有属性,若属性是对象或数组,则继续递归遍历直到遍历完整个对象树。这种递归的方式确保了深度监听能够监听到所有嵌套的属性的变化。
2年前 -
-
深度监听是 Vue 框架提供的一种数据监听方式,它能够监听到数据的变化是因为 Vue 在内部对数据进行了劫持和代理。
在 Vue 中,当一个对象被传入 Vue 实例进行响应式处理时,Vue 内部会通过使用 Object.defineProperty 方法对对象的属性进行劫持。Object.defineProperty 是 JavaScript 提供的一个方法,它可以定义一个对象的属性,并指定该属性的设置和获取方式。
在劫持过程中,Vue 通过在 get 方法中收集依赖,并在 set 方法中触发依赖更新。当我们使用深度监听时,Vue 会递归地遍历对象的所有属性,对每个属性进行劫持,进而实现了对整个对象及其嵌套属性的监听。
接下来,我们来看一下深度监听的操作流程。
- Vue 实例化
首先,我们需要将数据传入 Vue 实例进行响应式处理。我们可以通过在 Vue 实例的 data 选项中定义一个对象,并将这个对象传入 Vue 实例。
var vm = new Vue({ data: { obj: { name: 'Vue', version: '3.0', author: 'Evan You', }, }, });- 对象劫持
在 Vue 内部,会对传入的对象进行劫持。Vue 利用 Object.defineProperty 方法来定义对象的属性,并为每个属性添加 get 和 set 方法。
function defineProperty(obj, key, val) { Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter() { // 在这里收集依赖 return val; }, set: function reactiveSetter(newVal) { // 在这里触发依赖更新 if (newVal === val) return; val = newVal; }, }); }- 递归监听
在劫持过程中,对于对象类型的属性,Vue 会对其属性进行递归监听。这样,就能实现对整个对象及其嵌套属性的深度监听。
function observe(obj) { if (typeof obj !== 'object' || obj === null) { return; } Object.keys(obj).forEach(function (key) { defineReactive(obj, key, obj[key]); }); } function defineReactive(obj, key, val) { observe(val); // 递归监听子属性 Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter() { // 在这里收集依赖 return val; }, set: function reactiveSetter(newVal) { // 在这里触发依赖更新 if (newVal === val) return; val = newVal; }, }); }这样,Vue 就能够监听到对象的数据变化了。当我们修改对象的属性时,Vue 会触发相应的 set 方法,从而更新依赖。
总结一下,深度监听能监听到数据是因为 Vue 在内部对数据进行了劫持和代理。它通过递归遍历对象的属性,对每个属性进行劫持,从而实现了对对象及其嵌套属性的监听。深度监听使得当对象的属性发生变化时,Vue 能够及时地触发相应的更新操作。
2年前