数据更新

关于监视

  • 我们之前讲过,我们在data当中配置的属性,最终会挂载在vue实例身上,而data这个配置项,最终也会在vue身上成为一个新的属性 == _data

  • 当我们在页面DOM当中,去使用data当中的属性的时候,属性值发生变化,页面是不是会自动更新? 为什么会这样?
  • 你可以理解为 Vue底层默认有一个监视器,负责监视这些属性的变化
  • watchcomputed不同,这个监视是全局的,watch与computed是针对单独的,或者一些属性

不过目前可以说一句,watch与vue底层监视,用的是一套类似的逻辑

检测数据的原理

这个概念是非常重要的,所以这节课是不能跳过的,否则有一天会为这个行为买单(谢谢,已经买过了)

我们先来做个需求吧,这个需求不演示不行

  1. 你写一段代码,这个代码你需要修改data当中的数据
  2. 修改数据的行为,不能被vue检测到,也就是卡bug。
  3. 请你实现这个功能

准备工作

这是我的html设计,ul 当中的li标签渲染data当中persons这个数组的数据

button按钮呢,设置了一个点击事件,这个点击事件用来单独修改 马冬梅这个对象的信息

测试结果

可以看到,在这种赋值的情况下,我们成功的对 马冬梅 进行了修改数据

并且在vue当中也能检测到

卡bug,引出问题

既然是 对马冬梅进行修改,我们换一种方式来对他进行修改

为什么这次数据修改不成功了,这是为什么?

总结

  • 当我点击这个按钮的时候,在内存当中,persons[0]的数据确实发生改变了
  • 但是,这次修改并没有被vue所检测到
  • 至于控制台的数据到底修补修改,取决于你什么时候打开开发者工具

检测原理

vue是如何检测对象数据改变的

  • 我们先回顾一下关于vue的数据监测,详细博文
  • 我现在data这里有一个属性name和属性persons
  • 打开控制台,在vue实例身上也有这俩属性
  • 我们都知道,为什么这俩data当中属性会出现在vue实例身上,是因为做了数据代理
  • 在vue身上有个_data,这个下划线data当中包含着我们上图配置的data的所有数据,并且还对这个配置项data做了加工
  • 因为如果只是 将 data的值,赋给_data,那么二者的内容应该是相等的才是
  • 但是现在显然不是,说明这里做了加工
  • 为啥他要加工?
    • 它加工了就可以做响应式了

关于definedproperty

  • 之前说过,vue的数据代理definedProperty 这个API有关
  • 那么其内部是如何进行数据代理的呢?
  • 如果不使用 vue框架,我们能实现数据代理吗?
  • 我们来测试一下

错误测试

  • 按照正常的理解,如果我们需要对age这个属性进行数据代理
  • 让页面能够检测到数据的改变,那么就需要使用这个接口(defined......)
  • 那么这个接口的调用,需要如下几个配置
    • 要给谁添加属性
    • 属性名是什么
    • 配置项(getter和setter)
  • 那么对getter而言,如果该属性被访问到了,那么就需要返回该属性的值
  • 对setter而言,当属性值,发生修改,那么将接收到的修改的属性值,重新赋值给该属性

我们虽然添加的是age,但是这里的意思是将原有属性age覆盖掉,使用这个新的age

我们来看下测试结果

出现bug的原因

  • 其实这个问题很好理解,我们看下错误原因

  • 这是一个 无限递归产生的bug,该方法一直无限的被调用,从而产生了这个错误
  • 为什么呢?
  • 我们仔细看下这段代码
    1. 当,age属性被访问的时候,会调用get函数
    2. 调用get函数,会返回age
    3. 返回的过程当中,age是不是又被访问了
    4. 从而产生死循环,无限递归
  • 为什么无法修改属性呢?也是这个道理

所以,vue底层的数据代理,或者说数据加工没有我们想的这么简单,那么人家是怎么实现的呢

Observer

  • 在vue当中,有个接口叫做Observer,这个接口用来监视页面数据发生的变化
  • 不过他底层是如何进行监听的呢
  • 我们写不到底层那么详细,只写主要的部分

准备工作

1、首先我们准备一个data,这里面存放了两个属性,name和age

2、我们创建一个function ==> Observer

然后实例化这个 Observer,js当中,function是可以当做构造函数使用的

该函数需要一个属性,从参数名可以看出,这是一个对象属性

3、现在我们就来配置这个对象,首先我们需要获取到 data这个对象当中的所有key值

4、对这个数组,进行循环

5、在迭代的过程当中,使用definedProperty进行数据代理

参数解析,为什么这里,添加数据的对象(参数1) 是 this

  1. 使用this,那么就是给 this所指向的对象 ==> Observer;也就是我们刚刚实例化出来的对象

  2. 给它添加属性(property参数
  3. 那么接下来我们就在 参数三 当中配置get和set了

6、get和set

数组当中是可以用字符串来获取元素值的(很少)

完整代码

// 这有一个对象,对象有两个属性
let data = {
name: "waves",
age: 0
} // 实例化一个监视器对象
let observer = new Observer(data); // 监视对象Observer
function Observer(obj){
// 1、获取data当中的所有key值
let properties = Object.keys(data); // ["name","age"] // 2、迭代 properties数组
properties.forEach((property)=>{
// 3、在迭代的过程当中,使用definedProperty进行数据代理
Object.defineProperty(this,property,{
// 配置get和set
get(){
// 很简单,因为data没有做数据代理,返回data[property]即可
return data[property]; // data["name"] = waves
},
set(val){
// 赋值即可
data[property] = val
}
})
})
}

总结

  1. 我们这里设置了一个data

  2. 通过我们的一系列配置,data身上有的属性,Observer实例身上也有
  3. 并且,这个observer身上的属性都做了数据代理
  4. 当然,vue写的比我们完善的多
  5. 比如,如果data当中还存在对象怎么办?

vue在这里写了递归,一直找,找到这个属性不再是对象为止

数组也是一个道理,vue也能给你找出来,不过 关于数组和对象的代理,这二者的处理方式不同,下节会讲解

19_Vue如何监测到对象类型数据发生改变的?的更多相关文章

  1. 20_Vue如何监测数组类型数据发生改变的?

    通过上一节,我们知道了vue检测对象数据发生改变的原理 但是还有个api我们没有讲解,Vue.set(): 这个API比较适合在理解了对象检测的原理后进行讲解 案例准备 html <!-- 创建 ...

  2. iOS Foundation框架 -3.利用NSNumber和NSValue将非OC对象类型数据存放到集合

    1.Foundation框架中提供了很多的集合类如:NSArray,NSMutableArray,NSSet,NSMutableSet,NSDictionary,NSMutableDictionary ...

  3. Java操作Redis存储对象类型数据

    背景描述      关于JAVA去操作Redis时,如何存储一个对象的数据,大家是非常关心的问题,虽然官方提供了存储String,List,Set等等类型,但并不满足我们现在实际应用.存储一个对象是是 ...

  4. 将JSON字符串反序列化为指定的.NET对象类型

    目录导航: 前言: 方法一.在项目中定义对应的对象参数模型,用于映射反序列化出来的参数(复杂JSON字符串数据推荐使用): 方法二.直接将JSON字符串格式数据反序列化转化为字典数据(简单JSON字符 ...

  5. 2016年11月3日JS脚本简介数据类型: 1.整型:int 2.小数类型: float(单精度) double(双精度) decimal () 3.字符类型: chr 4.字符串类型:sting 5.日期时间:datetime 6.布尔型数据:bool 7.对象类型:object 8.二进制:binary 语言类型: 1.强类型语言:c++ c c# java 2.弱类型语

    数据类型: 1.整型:int 2.小数类型: float(单精度) double(双精度) decimal () 3.字符类型: chr 4.字符串类型:sting 5.日期时间:datetime 6 ...

  6. struts通过Ajax返回数据时,例如对象类型,没有执行Ajax的回调函数

    <result type="json"  name="success">                 <param name=" ...

  7. oracle中使用impdp数据泵导入数据提示“ORA-31684:对象类型已经存在”错误的解决

    转载请注明出处:http://blog.csdn.net/dongdong9223/article/details/47448751 本文出自[我是干勾鱼的博客] oracle中使用impdp数据泵导 ...

  8. js 对 只包含简单类型数据的对象 为元素 组成的数组 进行去重

    /** * 对于由简单类型数据组成的对象为元素组成的数组进行去重操作 * @params {Array} 需要去重的对象数组 * @returns {Array} 去重后的对象数组 */ functi ...

  9. EF里Guid类型数据的自增长、时间戳和复杂类型的用法

    通过前两章Lodging和Destination类的演示,大家肯定基本了解Code First是怎么玩的了,本章继续演示一些很实用的东西.文章的开头提示下:提供的demo为了后面演示效果,前面代码有些 ...

随机推荐

  1. CSS3(一)

    (一)CSS简介 CSS主要用来美化页面.布局页面 1.HTML的局限性 HTML主要是做结构,显示元素内容.只关注内容,但是丑.虽然可以做简单的样式,但是非常臃肿和繁琐 2.CSS网页的美容师 CS ...

  2. 向日葵远程RCE漏洞分析及漏洞利用脚本编写

    0x00 漏洞概述 向日葵是一款免费的,集远程控制电脑.手机.远程桌面连接.远程开机.远程管理.支持内网穿透等功能的一体化远程控制管理软件.如果想要手机远控电脑,或者电脑远控手机可以利用向日葵:如果是 ...

  3. Java jdk常用工具集合

    jdk 常用工具包目录: windows: 默认安装目录:C:\Program Files\Java\jdk1.8.0_152\bin> 1.查看Java进程 jps -l 查看当前机器的Jav ...

  4. 3-14 Python处理XML文件

    xml文件处理 什么是xml文件? xml即可扩展标记语言,它可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言. 从结构上,很像HTML超文本标记语言.但他们被设计的目的 ...

  5. C#通过反射实现简单的控制反转和依赖注入(一)

    Java项目中通过@Autowire便可以实现将对象实例化到指定的字段,无需手动new一个对象出来,用起来非常方便,因为Java类加载器在在加载过程会将扫描所有@Servie.@Mapper.@Com ...

  6. nginx的安装和配置

    目录 目录 一.购买下载SSL证书 二.修改Nginx配置信息 三.重启Nginx 一.购买下载SSL证书 SSL证书阿里云做活动期间可以免费申请,购买SSL证书时选择单域名-DV SSL-免费版即可 ...

  7. 读完 RocketMQ 源码,我学会了如何优雅的创建线程

    RocketMQ 是一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时.高可靠的消息发布与订阅服务. 这篇文章,笔者整理了 RocketMQ 源码中创建线程的几点技巧,希望大家读完之后,能 ...

  8. HCNP Routing&Switching之ARP安全

    前文我们了解了IP安全相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/16652367.html:今天我们来聊一聊ARP安全相关话题: 什么是ARP? ...

  9. Kubernetes 监控:Prometheus Operator + Thanos ---实践篇

    具体参考网址:https://www.cnblogs.com/sanduzxcvbnm/p/16291296.html 本章用到的yaml文件地址:https://files.cnblogs.com/ ...

  10. 使用Fluentd进行简单流处理

    在某些日志采集场景中,我们需要对数据流进行一些转换.比如,我们可能需要从日志记录中提取某些字段以进行错误告警,或向日志记录中插入新的字段用以后续的分析. 本文简单介绍一下使用Fluentd进行数据操作 ...