【Vue】数据检测原理

前言
Vue中的数据监听离不开Object.defineProperty()方法的使用,在了解数据监测原理之前,建议先掌握defineProperty的用法。
目标

1 数据监测问题
2 数据监测原理
3 如何实现数组更新

1 遇到的问题

数组更新问题

<button @click="updatePeople">更新一个用户信息</button>
<ul>
   <li v-for="(item,index) in people" :key="index">
      {{item.name}}----{{item.age}}
   </li>
</ul>
// 可以实时更新
updatePeople(){
     console.log('更新用户信息')
     this.people[0].name = '马冬梅'
     this.people[0].age = '40'
},

在这里插入图片描述

updatePeople(){
     console.log('更新用户信息')
     // 实时更新页面失败
     this.people[0] = {name:'马冬梅',age:40}
},

在这里插入图片描述
vue中的数据更新主要通过Object.defineProperty()中的set来实现的,people数组下的对象没有get与set,而对象中的name、age有set,所以在设置name、age值时会同步的进行更新
在这里插入图片描述

Vue.set()

现有一个需求:在页面渲染完成后,动态的给对象添加属性,并打印属性与属性值。
看似很好实现的一个需求,但是当我们的动态的添加属性后,也页面却无任何更新,这是为什么呢?
给data中的属性绑定get、set是在new Vue()的过程中进行绑定的,但是动态添加属性是在绑定之后,也就是后来添加的属性无set,修改值就无法试试的去监测数据更新了。
在这里插入图片描述
为了解决此问题,Vue提供了Vue.set方法,用于添加响应式的property
Vue.set() 与 vm.$set()时一样的效果
Vue.set(vm.pseron,'sex','男生') === vm. $set(vm.pseron,'sex','男生')
Vue.set()也不是任何情况下都可以使用的,若作用的对象是Vue实例或者实例的根数组对象,会无效
在这里插入图片描述

data:{
  pserson: {
        name: "李四",
        age: 32,
        children: {
          name: "王五",
          age: 6,
        },
      }
 }
<ul>
    <li v-for="(value,key,index) of pserson" :key="index">
       {{key}}----------{{value}}
    </li>
</ul>

在这里插入图片描述

2 Vue检测数据原理

1 对象

在讨论如何解决数组更新问题之前,先来看一下对象是如何实现实时更新的。
详细的就不再描述了,不了解的可以去看看vue 【vue中的数据代理】
对象代理流程大致是:

加工
触发
set
data中的数据
vm._data
修改data.name
页面更新

简单写个例子来模拟一下Vue中对象的数据监听。Vue中对象的数据监听用的也是Object.defineProperty,通过递归遍历对象,确保对象中的每个属性值都有get与set

<script type="text/javascript">
  let data = {
    name: '张三',
    age: '18'
  }
  const obs = new Observer(data)
  let vm = {}
  vm._data = data = obs
  function Observer(obj) {
    const keys = Object.keys(obj)
    keys.forEach(key => {
      Object.defineProperty(this, key, {
        get() {
          return obj[key]
        },
        set(val) {
          obj[key] = val
        }
      })
    });
  }
  </script>

在这里插入图片描述
在这里插入图片描述

Vue.set()

现有一个需求:在页面渲染完成后,动态的给对象添加属性,并打印属性与属性值。
看似很好实现的一个需求,但是当我们的动态的添加属性后,也页面却无任何更新,这是为什么呢?
给data中的属性绑定get、set是在new Vue()的过程中进行绑定的,但是动态添加属性是在绑定之后,也就是后来添加的属性无set,修改值就无法试试的去监测数据更新了。
在这里插入图片描述

data:{
  pserson: {
        name: "李四",
        age: 32,
        children: {
          name: "王五",
          age: 6,
        },
      }
 }
<ul>
    <li v-for="(value,key,index) of pserson" :key="index">
       {{key}}----------{{value}}
    </li>
</ul>

在这里插入图片描述

  • 如何监测对象中的数据?
    通过setter实现监视,且要在new Vue时就传入要监测的数据。
    (1).对象中后追加的属性,Vue默认不做响应式处理
    (2).如需给后添加的属性做响应式,请使用如下API:
    • Vue.set(target,propertyName/index, value) 或 vm.$set(target,propertyName/index, value)

2 数组

当数组中对象的属性发生变化时,属性可以实时的监听。但是我们整个改变数组的中的值时,页面却没有实时更新。
在这里插入图片描述
我们用数组方法往数组中添加对象,这个对象中的属性也是响应式的

  • 如何监测数组中的数据?
    通过包裹数组更新元素的方法实现,本质就是做了两件事:
    • (1).调用原生对应的方法对数组进行更新。
    • (2).重新解析模板,进而更新页面。
  • 在vue修改数组中的某个元素一定要用如下方法:
    • 1.使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()。用如下方法向数组中添加对象,对象中的属性也是响应式
    • 2.Vue.set()或 vm.$set()
  • 特别注意: Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添属性!!!
    在这里插入图片描述
  • 25
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Vue.js 的双向数据绑定的原理是通过 Object.defineProperty 来实现的。 当 Vue 实例创建时,它会遍历 data 对象中的每一个属性,使用 Object.defineProperty 将这些属性转换为 getter/setter。 在 Vue 实例中,每个组件都是一个单独的作用域,当绑定的数据发生变化时,Vue 实例通过 getter/setter 检测到变化,并触发相应的视图更新。 通过这种方式,Vue 实现了数据与视图之间的双向绑定,可以让开发者可以只关注数据的更新,而不需要关注视图的更新。 ### 回答2: Vue.js 是一种基于 MVVM 模式的前端框架,其提供了双向数据绑定的能力。双向数据绑定意味着当数据发生改变时,视图会自动更新;反之,当视图发生改变时,数据也会相应地更新。 Vue 的双向数据绑定原理主要依靠了它的响应式系统。当我们在 Vue 的实例中声明了一个数据属性时,Vue 会使用 Object.defineProperty() 方法将该数据属性转换为 getter 和 setter。这样,当我们通过 Vue 实例访问该数据属性时,实际上是调用了 getter 方法,从而获得该数据属性的值;当我们修改该数据属性的值时,实际上是调用了 setter 方法,从而更新数据属性的值。 Vue 在实例化时会对模板进行解析,将模板中的指令、表达式等转换为对应的数据绑定。例如,将 "{{ message }}" 转换为数据属性 "message" 的使用。 当数据发生改变时,Vue 的响应式系统会通过依赖追踪机制,收集与该数据属性相关的依赖(例如视图中使用了该数据属性的地方)。当数据属性的 setter 方法被调用时,Vue 会通知相关的依赖更新视图,从而实现了数据的双向绑定。 另外,在视图中,Vue 通过使用指令和表达式等语法糖来实现数据的绑定。例如,v-bind 指令可以将一个属性和一个表达式绑定,当表达式的值发生变化时,属性的值也会相应更新。 综上所述,Vue 的双向数据绑定原理主要依赖于它的响应式系统,通过对数据属性的 get 和 set 方法进行拦截和监听,实现了数据的双向绑定。同时,Vue 还提供了丰富的语法糖,便于开发者进行数据绑定的操作。 ### 回答3: Vue.js的双向数据绑定是通过Vue实例中的数据监听器和指令来实现的。 首先,Vue会将页面中的模板解析成AST(抽象语法树)并创建渲染函数。当数据发生变化时,Vue会重新执行渲染函数并生成新的虚拟DOM树。 在数据监听器部分,Vue会使用Object.defineProperty来重写数据对象的get和set方法。这样一来,当我们读取数据时,Vue会将该属性添加到依赖收集器中。而当我们修改数据时,Vue则会通知订阅者,执行相应的更新操作。 指令的作用是将视图和数据进行绑定。Vue中的v-model指令可以实现双向数据绑定,它会根据不同的输入元素类型创建不同的事件监听器,并在值改变时更新数据。 具体地说,当我们在输入框中输入内容时,触发的input或change事件会被v-model指令监听到,并将输入的值赋给数据。而当数据发生变化时,数据监听器会通知订阅者,订阅者再通过渲染函数更新视图,以保持数据和视图的同步。 另外,Vue还通过虚拟DOM和Diff算法来优化性能。当数据发生变化时,Vue会比较新旧虚拟DOM树的差异,然后只更新需要变化的部分,避免重新渲染整个视图。 总的来说,Vue的双向数据绑定原理是通过数据监听器和指令来实现的。数据监听器通过重写数据对象的get和set方法来收集依赖和触发更新,而指令则负责将视图和数据进行绑定和更新。通过这种机制,数据和视图可以实现实时同步,极大地提高了开发效率和用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱编程的小学究

愿你有所收获

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值