Vue.js的核心包括一套“响应式系统”。“响应式”,是指当数据改变后,Vue会通知到使用该数据的代码。例如,视图渲染中使用了数据,数据改变后,视图也会自动更新。

1. ES语法的getter和setter

在开始了解 Vue 的数据响应式原理前应该先搞清楚 ES语法 中的 getter 和 setter 方法的具体用法。

getter和setter 方法是以 get 和 set 关键字来为对象添加虚拟属性的一种方式。这种属性其实并不真实存在,而是以取值函数 getter 和存值函数 setter 来模拟的一种属性。目的是对某个属性设置存值函数和取值函数,拦截该属性的存取行为,以便于对该属性的存取做一些限定处理。如下所示(以下代码来源于 mdn)

getter 方法

const obj = {log: ['a', 'b', 'c'],get latest() { //在正常方法前加 get 关键字if (this.log.length == 0) {return undefined;}return this.log[this.log.length - 1];}
}console.log(obj.latest);// 输出 c,获取的是属性名不用带括号

setter方法

const language = {set current(name) {this.log.push(name);},log: []
}language.current = 'EN';
language.current = 'FA';console.log(language.log);//输出 Array ["EN", "FA"]

2. ES语法的 defineProperty

defineProperty 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象,可用于在一个对象定义好后为其修改或添加属性。
语法为:

Object.defineProperty(obj, prop, descriptor)

添加常规属性:

let data = {m: 0
}Object.defineProperty(data, 'n', {value: 1 //添加属性的 value 就是其值
})
console.log(`${data.n}`) //则会输出n值为1

也可用来添加 getter 和 setter 的虚拟属性

let data1 = {_n: 0
}Object.defineProperty(data1, 'n', {get(){return this._n}, set(value){if(value < 0) returnthis._n = value}//直接写明 get / set 即可
}) //由于指明了虚拟属性为 n,即 get n(){}、set n(value){},因此在函数定义时就不用再写n了

3. Vue对数据的代理和监听

代理,即 proxy,简单来说我自己的一些事情我自己不亲自处理,而是交给一个人让他去帮我做,那个做事的人就是代理。这个逻辑中有两个关键点需要搞清楚,代理是处理操作的人,而其处理操作的事情不属于他,而是属于委托其代理的人的。

因此类比到 Vue数据代理 ,委托代理的是 data{} 数据对象,其找到代理就是 Vue实例vm ,data{} 数据对象要代理 vm 做的事情是管理 data{} 数据对象里数据操作。因此 data{} 数据对象只负责内部数据的生产即可,对生产出来的数据的管理和操作全权交给 vm 处理。

那么 vm 如何对 data{} 数据对象里的数据进行控制和操作呢?换句话说,vm 如何在 data{} 数据对象里面的任意一个属性值变化时都及时知道呢?

于是便用到了 ES 语法中的 getter和setter 方法,通过 getter和setter 方法控制的属性的任何操作都会被这两个函数检测到,而 getter和setter 方法形成的属性是虚拟属性,真实并不存在,因此如果用户想私自不经过代理 vm 直接修改 data{} 数据对象的属性也获取不到对应的实体属性,只能通过 getter和setter 方法修改,那么其修改就必定被 vm 检测到。

因此 vm 为了实现对 data{} 数据对象里数据的全部控制,就必须在 Vue实例 创建的时候对传进来的 data{} 数据对象做一些处理,做的处理就是将 data{} 数据对象里的属性都变成了 getter和setter 方法控制的虚拟属性,并保存在代理数据对象 obj 并返回。

但为了不让用户直接修改原来的 data{} 属性,也将原来的 data{} 对象的实体属性全改变了,添加的虚拟属性名字和实体属性名一样,就会用虚拟属性覆盖原来的实际属性,用户在修改属性值是就是通过 getter和setter 方法修改的虚拟属性。这样一来 data{} 数据对象的全部属性的任何变化都会被 Vue实例vm 检测到。

let myData = {n:0}
let data = proxy({ data:myData }) // 类似于 let vm = new Vue({data: myData})function proxy({data}/* 解构赋值*/){let _n = data.nObject.defineProperty(data, 'n', { //覆盖原来的data.n属性get(){return _n},set(newValue){if(newValue<0)return_n = newValue}})// 改变data{}数据对象本身属性,可通过闭包形成上下文,让原来的实际属性值存在闭包的上下文_n中const obj = {}Object.defineProperty(obj, 'n', {get(){return data.n},set(value){data.n = value}}) //添加data{}数据对象的代理,对data{}数据对象操作return obj // obj 就是data{}的代理
}

4. Vue的数据响应式

所谓响应式就是当事物发生变化时会根据变化做出相应的反映。

Vue 中的数据 data 是响应式的,由上述 Vue 通过 Object.defineProperty()函数 来用 getter和setter方法 对 data 数据做了代理和监听,一旦数据发生变化,Vue 就会改变数据对应的 UI 视图,这就是 Vue的数据响应式

但是 Vue 使用 Object.defineProperty 来设置监听,就只能对在 Vue实例化 时 data 对象里已经存在的属性设置监听,而对不存在的或者后来添加进去的属性没有进行监听。

为了解决这个问题,有两种方法:

1. 将所有属性都提前声明好

2. 使用 Vue.set 和 this.$set 添加属性

使用 Vue.set 和 this.$set 添加属性是会通知 Vue 对这后添加的属性也设置监听操作。

Vue.set('this.data','m','10')
this.$set('this.data','m','10')//为vm的data对象添加属性m值为10

3.数组变异

对于数组的数据增加,无法控制其新增个数因此不能提前声明所有数据值,而一个一个 set 又太麻烦,而且数组是常用的对象数据类型中的一种,因此 vue 的作者就对数组的增删函数如 push 和 pop 等进行了篡改,用户在使用 vue 中数组增删时仍是用 push 和 pop ,但是里面进行了额外的处理,这几个被篡改的 API 会对数组新增是数据代理监听并根据数据响应改变 UI 视图。

以上就是深入理解Vue的数据响应式的详细内容。

详细介绍Vue的数据响应式相关推荐

  1. vue 数组长度_深入理解Vue的数据响应式

    什么是响应式 当一个物体对外界的变化做出反应就叫响应式的,如"我打你一拳,你会喊疼". Vue的数据响应式 就是对数据做出改变时,视图上也会做出相应的变化. 举个例子 1const ...

  2. Vue源码解读一:Vue数据响应式原理

    这方面的文章很多,但是我感觉很多写的比较抽象,本文会通过举例更详细的解释.(此文面向的Vue新手们,如果你是个大牛,看到这篇文章就可以点个赞,关掉页面了.)通过阅读这篇文章,你将了解到: 1.Vue数 ...

  3. chrome vue 未响应_VUE数据响应式

    响应式顾名思义就是对外界的触发变化做出响应. 在vue中,vue的data是响应式的,我们会很好奇,为什么传入new Vue({})中的data在做出变化的时候,UI中相应地显示的数据也会响应做出变化 ...

  4. vue data数据修改_VUE的数据响应式

    什么是数据响应式? const vm =newVUE({data:{n:0}}) 上面的代码中,如果修改vm.n,那么UI中的n就会通过变化来响应我,这就是数据响应式. VUE对data做了什么? 当 ...

  5. 彻底理解Vue数据响应式原理

    彻底理解Vue数据响应式原理 当创建了一个实例后,通过将数据传入实例的data属性中,会将数据进行劫持,实现响应式,也就是说当这些数据发生变化时,对应的视图也会发生改变. const data = { ...

  6. php可以实现响应式吗,怎么实现Vue数据响应式

    这次给大家带来怎么实现Vue数据响应式,实现Vue数据响应式的注意事项有哪些,下面就是实战案例,一起来看一下. 前言 Vue的数据响应主要是依赖了Object.defineProperty(),那么整 ...

  7. Vue深入学习3—数据响应式原理

    1.数据响应式原理 1.1.MVVM是什么? 简单来说,就是数据变了,视图也会跟着变,首先你得定义一个带有{{ }}的模板Model,当数据中的值变化了,视图View就会跟着变化:视图模型View-m ...

  8. vue set方法_Vue 数据响应式

    数据响应式是指当数据改变后,会通知到使用该数据的代码.例如,视图渲染中使用了数据,数据改变后,视图也会自动更新. new Vue内部对data的代理和监听 data的bug 由于使用了Object.d ...

  9. vue是怎么实现数据响应式的?

    数据响应式原理核心就是采用了 defineReactive,defineReactive里的Object.defineProperty对每个属性进行监听对数据进行拦截,把这些属性全部转成getter/ ...

最新文章

  1. ADC和DAC中多通道的含义
  2. 解决频率选择性衰落的措施_螺杆压缩机,振动怎么办?解决办法在这里
  3. 《延世大学韩国语教程2》第十九课 生病(下)
  4. java植树问题代码,小学数学最难的13种典型题,让孩子吃透了,拿高分不难!
  5. IBM Cognos 10 启动报错
  6. 3dsMax建模,卡线学习笔记
  7. 什么叫SYN包,什么是SYN包***?
  8. 一文理解主数据和参考数据
  9. 微信拍一拍怎么撤回(无法撤回原因是这样的)
  10. 小程序微商城-商铺管理后台
  11. 武汉理工大学有计算机专业,武汉理工大学计算机专业属于什么系
  12. [转载] Ruby、Rails、Agile的启示
  13. python四舍五入round_Python四舍五入及round、Decimal使用
  14. 全球十大正规外盘期货交易APP平台排名(2022版)
  15. Linux系统安全应用
  16. python制作一个密码簿_[python]制作密码薄,完成增删改查和文件存储功能。
  17. bzoj2754:[SCOI2012]喵星球上的点名 (后缀数组+离线+树状数组)
  18. 雷锋网专访路客网合伙人、COO王鑫光
  19. okhttp 服务器性能,OkHttp逐步深入
  20. 阿里云服务器mysql安装

热门文章

  1. IntelliJ IDEA 常用设置注释提示
  2. docker依赖的技术探索
  3. Vue之Todolist案例和ES6语法
  4. 教你如何利用DroidCam将手机摄像头用作电脑摄像头|瞬间提升画质!
  5. 线程和进程有什么区别?
  6. 长知识啦!字符也可以作为下标!_只愿与一人十指紧扣_新浪博客
  7. 视觉实战|使用人工神经网络进行图像分类
  8. GaitSet:通过交叉视角步态识别
  9. 【OpenCV 4开发详解】形态学应用
  10. iOS 生成二维码/条形码