一、数据代理

1.什么是数据代理?

数据代理:通过一个对象代理对另一个对象中属性的操作

2.Vue数据代理

通过vm对象来代理配置对象data中所有属性的操作。
(如果想访问data里的数据,可以直接通过实例对象,如vm.name,vm.age拿到具体的数值,之所以能这样做,就是因为Vue实现了数据代理)

3.为什么要用数据代理

更方便的读取和修改data中的属性

4.为什么要先将数据收集到_data中,再代理出去

为了更高效地实现数据监测

5.实现原理

①Vue将配置对象data进行了一次加工,然后将加工后的数据收集到vm._data中,实例对象通过vm._data的方式可以拿到加工后的data。但是属性的值不再直接给出,而是通过响应式getter来获取,当data中数据改变的时候,就会调用响应式setter,导致重新解析模板,然后生成新的虚拟DOM进行新旧DOM对比,最后更新页面。

②然后通过Object.defineProperty()让vm上拥有vm._data中的所有属性,即配置对象data中的所有属性,从而实现了数据代理。

模拟数据绑定到vm._data的过程:

   <script type="text/javascript">let data={name:"gyc",age:18}// 创建一个Observer实例对象,用于监视data中所有属性的变化const obs=new Observer(data)console.log(obs)// 准备一个vm实例对象let vm={}//将obs赋值给vm._data,从而vm._data可以监视data中属性的变化vm._data=data=obsfunction Observer(obj){//获取监视对象obj的所有属性const keyArr=Object.keys(obj)// 遍历属性,将obj的所有属性定义给Obeserver实例对象keyArr.forEach((key)=>{Object.defineProperty(this,key,{get(){return obj[key]},set(val){obj[key]=val}})})}</script>


注意:_data里面不是数据代理,而是做了一个数据劫持。Vue去监测_data中的数据变化,从而达到界面也跟着变化。
添加到vm上的属性才是数据代理

二、数据监测

1.监测对象

首先写出需要用到的静态页面:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>更新数据</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root"><h2>学校名称:{{name}}</h2><h2>学校地址:{{address}}</h2><hr/><h2>学生姓名:{{student.name}}</h2><h2>学生性别:{{student.sex}}</h2><h2>学生年龄:{{student.age}}</h2><h1>朋友</h1><ul><li v-for="(f,index) in student.friends" :key="index">{{f.name}} - {{f.age}}</li></ul></div><script type="text/javascript">Vue.config.productionTip = falseconst vm = new Vue({el: '#root',data:{name:'JLU',address:'jilin',student:{name: 'gyc',age: 20,friends: [{name: 'jack', age: 21},{name: 'mary', age: 20}]},}})</script>
</body>
</html>


需要注意的是,模板中的{{sex}}并没有出现在data中。当输出一个对象中不存在的属性值时,会输出undifined,但经过Vue处理后,不会将undifined显示到页面上,而是什么都不显示,控制台也不报错。

现在的需求是,添加一个按钮,点击按钮,为学生添加性别属性。要求不能改变data中现有的属性,即sex不能直接添加到data中。

前面提到过_data,考虑将sex添加到_data中,浅试一下:

页面效果:

可以发现,添加的sex属性并没有渲染到页面上
查看vm._data:

可以看到通过这种方式添加属性,_data中添加了sex,但是没有生成相应的setter和getter,这说明后添加的属性不是响应式属性,无法渲染到页面上。

2.Vue.set监测对象

为了解决上面的问题,为后添加的属性设置响应式,需要使用Vue提供的API:
​ Vue.set(target,propertyName/index,value)
​ vm.$ser(target,propertyName/index,value)

通过Vue.set()试一下是否可以实现功能:

页面效果:

发现通过这种方式可以将新添加的属性渲染到页面上。
在实现功能后我们可以考虑一下优化简写,由于数据代理,vm.student === vm._data.student,所以可以简写为Vue.set(vm.student,‘sex’,‘女’)。

完整的实现上面提出的需求:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>更新数据</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root"><h2>学校名称:{{name}}</h2><h2>学校地址:{{address}}</h2><hr/><h2>学生姓名:{{student.name}}</h2><button @click="addSex">点击添加性别</button><h2 v-show="student.sex">学生性别:{{student.sex}}</h2><h2>学生年龄:{{student.age}}</h2><h1>朋友</h1><ul><li v-for="(f,index) in student.friends" :key="index">{{f.name}} - {{f.age}}</li></ul></div><script type="text/javascript">Vue.config.productionTip = falseconst vm = new Vue({el: '#root',data:{name:'JLU',address:'jilin',student:{name: 'gyc',age: 20,friends: [{name: 'tom', age: 19},{name: 'richard', age: 20}]},},methods:{addSex(){Vue.set(this.student,'sex','女')}}})</script>
</body>
</html>


但是使用这样的方法有一定的局限性,上面的例子是给data中的student对象添加新的属性,假如直接给data对象添加属性呢?
比如假设需要在这里添加一个新的属性建校事件time,如果仍然采用Vue.set方法的话,就会报错。

注意:Vue.set只适用于给data中的对象添加新的属性(例如:data.student),而不能直接给data添加新的属性。

3.监测数组

先给出静态页面:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>更新数据</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root"><button @click="addSex">点击按钮新增性别</button><h2>学校名称:{{name}}</h2><h2>学校地址:{{address}}</h2><hr/><h2>学生姓名:{{student.name}}</h2><h2>学生性别:{{student.sex}}</h2><h2>学生年龄:{{student.age}}</h2><h1>朋友</h1><ul><li v-for="(f,index) in student.friends" :key="index">{{f.name}} - {{f.age}}</li></ul><h1>爱好</h1><ul><li v-for="(h,index) in student.hobby" :key="index">{{h}}</li></ul></div><script type="text/javascript">Vue.config.productionTip = falseconst vm = new Vue({el: '#root',data:{name:'JLU',address:'jilin',student:{name: 'gyc',age: 20,friends: [{name: 'tom', age: 19},{name: 'richard', age: 20}],hobby:['吃饭','睡觉','打豆豆']},},methods:{addSex(){this.$set(this.student, 'sex', '男')}}})</script>
</body>
</html>

其中student.hobby是数组
此时页面效果为:

在控制台中打印vm._data后我们可以清晰的看到,对于student中的hobby数组,数组整体来说有get和set,是响应式的。但是数组里面的元素并非响应式,而是简单的挂在了数组中。

现提出一个需求,将hobby数组中的第一项 吃饭 改成 学习。
如果通过索引来改变数组中的值,将hobby[0]改为学习:

vm._data中已经修改了,但是没有渲染到页面上,页面没反应:

在Vue中,如果想要通过索引修改数组中的数值,就需要使用某些特殊方法

Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:

push()
pop()
shift()
unshift()
splice()
sort()
reverse()

这些方法都会引起数组本身的变化,称为变更方法

因此,想要实现上面提出的需求,可以通过以下两种方法实现:
①通过splice()方法

vm.student.hobby.splice(0,1,'学习')

②通过Vue.set()

Vue.set(vm.student.hobby,0,'学习')

注意这里Vue.set()的第二个参数是数组中元素的下标。

对于一些数组的非变更方法,例如filter()、concat() 和 slice(),并不会引起数组本身的变化,若想要调用这些方法实现响应式,可以用新数组替换旧数组。例如:

 this.student.hobby=this.student.hobby.filter((item)=>{return item!='吃饭'})

4.Vue监测总结

1.vue会监视data中所有层次的数据2.如何监测对象中的数据?​ 通过setter事件监视,且要在new Vue时就传入要监测的数据​ (1).在对象后追加的属性,Vue默认不做响应式处理​ (2).如需给后添加的属性做响应式,需要使用以下API:​ Vue.set(target,propertyName/index,value)​ vm.$ser(target,propertyName/index,value)3.如何监测数组中的数据?​    通过包裹数组更新元素的方法实现,本质就是做了两件事:​ (1).调用原生对应的方法对数组进行更新​        (2).重新解析模板,进而更新页面4.在Vue修改数组中的某个元素需要用到以下方法:​    1.使用这些API:push(),pop(),shift(),unshift(),splice(),sort(),reverse()​ 2.Vue.set()或vm.$set

Vue数据代理与数据监测相关推荐

  1. vue面试核心,双向数据绑定,数据代理,数据劫持,发布订阅,数据编译,看这个demo就够了

    vue面试核心,双向数据绑定,数据代理,数据劫持,发布订阅,数据编译,看这个demo就够了. 不在怕面试官,你给我怼过去.复制到html文档,浏览器运行即可. mvvm原理剖析 {{singer}}

  2. Vue中的数据代理与数据劫持

    数据代理 数据代理字面上是通过一个对象代理对另一个对象属性的操作 在vue中的数据代理,实际上是通过vm上的属性代理对_data中属性的操作 数据劫持 数据劫持也可称作数据代理,字面上是劫持到某个属性 ...

  3. Vue数据代理的原理

    前言 Vue的数据代理的原理是十分重要的,它的学习对我们了解Vue的底层工作原理以及学习Vue具有举足轻重的作用,掌握了数据代理的原理,我们便可以由浅入深,再去学习Vue的响应式原理:因此本篇文章我将 ...

  4. Vue2(一):初识Vue、模板语法、数据绑定、el和data的两种写法、MVVM、数据代理、事件

    Vue2学习笔记:第一章 一.初识Vue 1. Vue的特点 2. Vue实例中的el和data 3.总结 二.模板语法 1.插值语法 2.指令语法 三.数据绑定 1.单向数据绑定(v-bind) 2 ...

  5. get vue 和set 用法_深入剖析Vue源码 - 数据代理,关联子父组件

    简单回顾一下这个系列的前两节,前两节花了大篇幅讲了vue在初始化时进行的选项合并.选项配置是vue实例化的第一步,针对不同类型的选项,vue提供的丰富选项配置策略以保证用户可以使用不同丰富的配置选项. ...

  6. vue 代理设置 访问图片_详解Vue源码之数据的代理访问

    概念解析: 1) 数据代理: 通过一个对象代理对另一个对象(在前一个对象内部)中属性的操作(读/写) 2) vue 数据代理: 通过 vm 对象(即this)来代理 data 对象中所有属性的操作 3 ...

  7. 【精讲】vue数据绑定、数据内容的应用、数据结构、数据代理

    目录 简介 vue数据绑定 数据内容的应用 数据结构 数据代理 知识点拓展 简介 vue是一款实用的框架,他可以大大提高我们编写项目的速度.在之前的板块中,我们聊过vue框架的实用性,在这一板块,我们 ...

  8. 从零学习Vue - 02模板语法、el与data两种写法、mvvm模型、数据代理

    root容器里的代码被称为模板,有了模板会有特殊的模板语法.Vue模板中语法有两大类,一类是插值语法,另一类是指令语法. 插值语法 功能:用于解析标签体内容.写法:{{xxx}},xxx为js表达式, ...

  9. VUE的el和data的写法以及MVVM模型、VUE的数据代理

    第一.VUE的el和data的两种写法: el的两种写法如下: 第一个形式如下: const v = new Vue({//第一种el的写法el:'#demo',data: {name: '三清祖师' ...

最新文章

  1. CCF-CSP 201712-2 游戏(C++实现)
  2. 工控设备 如何将数据发送到串口_实现4G无线通信透传的远程通信多组网5个PLC相互交换数据...
  3. 关于getCurrentUrl的获取问题
  4. 两个分布的特征映射_DDC:直接对齐特征空间进行领域自适应
  5. 在python中字符串可以使用什么来表示_Python 字符串定义
  6. 语言差异引起的问题解决一例
  7. RTX5 | 消息队列06 - (实战技巧)FDCAN接收中断ISR同步线程
  8. Magento: 左栏筛选条件 Select Box / Button / Dropdown List on Layered Navigation
  9. Linux操作系统基础解析之(四)——Linux基本命令剖析(2)
  10. json-lib javabean转换为首字母大写的json串
  11. 【附详细材料清单】一种不需要额外加工零件的板球结构(可修改后用于电赛板球结构)
  12. angular应用coreui框架
  13. 大数据经典案例与谬误
  14. idea切换Git分支时弹出Git Checkout problem
  15. 【不积跬步_无以至千里】 数学知识(不定时整理)
  16. 2008年7月28号,晴。时间在流逝——哈佛自习墙,今天是我攻读博士的第22天,昨天的收获还是不小的,至少让我明白,做任何事情,一定要尝试,一定要亲自动手
  17. 齐纳二极管 稳压二极管 SOD123封装 正负区分
  18. 小米手机计算机无法归零,小米体脂秤不归零怎么调
  19. 简单易懂的Json的使用教程(jackson/fastjson)
  20. 在c语言程序中使用数据库,数据库与C语言程序设计两者之间有什么联系?

热门文章

  1. bzoj 4563 [Haoi2016]放棋子 错位排列+高精度
  2. SpringBoot入门之简单配置
  3. hibernate悲观锁,乐观锁
  4. vs2013 中HTML页 无法在设计窗口中查看的解决
  5. Spring的javaMail邮件发送(带附件)
  6. 今天被BSE指摘了2个问题,感觉很典型
  7. 为memcached增加缓存依赖的性能测试
  8. JVM 字节码 对照表
  9. python爬虫:爬取某网站视频
  10. python全网表情包_Python爬虫爬取最右公众号表情包资源