本篇内容对应课程第144-143节
课程 P144节 《reactive函数》笔记
验证 reactive 只能处理对象类型数据,不能处理基本类型数据:当使用reactive处理一个基本类型数据时,控制台直接报出了警告:reactive不能处理基本类型数据。
使用reactive定义对象类型数据,打印被reactive加工后的数据,发现原来的对象被reactive加工成了一个Proxy对象:
对比之前用ref加工的对象类型数据,是一个 RefImpl 对象,里面的 value 属性是一个Proxy对象。ref在处理对象类型数据时,内部仍然是借助了 reactive 。
验证 reactive 加工后的对象类型数据是否是深层次响应式的:结论是是深层次响应式的。
验证 reactive 处理数组类型数据:发现可以直接通过数组索引去修改数据,且页面也可以捕获到数据的修改并更新视图。这在vue2中是不行的,需要借助一个方法 Vue.set 或 this.$set 来实现。
总结:
课程 P145节 《回顾vue2的响应式原理》笔记
先来回顾一下vue2中的响应式原理:
对象类型:通过 Object.defineProperty() 对属性的读取、修改进行拦截,也就是数据劫持。数据劫持是 响应式的根基,只有劫持到数据的改变,才可能实现响应式。
数组类型:当你调用数组的push方法时,其实调用的是vue经过二次封装的push方法,在这个方法里,vue做了两件事:一是帮你去正常地调用数组的push方法,二是去更新界面。
在vue2中,直接给对象数据添加一个属性,以及删除一个已有属性,可以看到数据可以修改成功,但vue2监测不到数据的改变,不会进行视图更新。
只能通过 this.$set 或Vue.set 的形式去实现数据修改的同时更新视图。
在vue2中,通过数组下标的方式修改数组某一项的值,同样是数据已经改变但视图不会更新。通过 this.$set 或Vue.set 的方式或者调用数组的更新方法 splice 方法来达到更新视图的目的。
课程 P146节 《vue3响应式原理》笔记
在vue3中,给响应式数据增加一个属性或删除一个已有属性,以及通过下标方式修改数组某一项(之前reactive一节已验证)数据都可以实现响应式,页面会更新。
模拟vue2中实现响应式:
通过对象p修改属性,发现可以被监测到:
通过p对象添加一个属性,会发现新添加的属性与原有属性不同,它没有对应的getter和setter,只是一个普通的属性。
通过p对象删除一个属性name,发现返回了一个false,同时发现p上面的name属性还在:
删不掉的原因是,在Object.defineProperty 中的配置中,没有加入 configurable:true :
模拟vue3中实现响应式:通过 new Proxy 得到一个代理对象,它接收两个参数,第一个为源对象,第二个参数是配置对象,如果不写任何配置,也必须要传递一个空对象,不允许不传递第二个参数:
输出代理对象p,可以看到它拥有与源对象相同的属性与值:
通过p对象修改、添加和删除属性,会发现源对象person上的相应属性也会被修改:
为了让修改数据时可以被监测到,我们在 new Proxy 的第二个参数配置对象中添加一些配置:get函数和set函数:
此时再次通过p对象修改属性,可以被监测到了:
为了使删除属性时也被监测到,增加 deleteProperty 配置,在这个配置中,需要用 delete 关键字真正删掉操作删除的属性:
测试删除属性:当删除p身上的name后,删除的动作被监测到了,同时 person 和 p 身上的name属性都被删除掉了。删除语句执行后返回了一个false:
这是因为绿色框的代码, deleteProperty 方法没有返回值,相当于返回了 undefined,也就是 false:
给 deleteProperty 方法设置返回值:
此时再次执行删除属性操作,就会返回删除结果了,如果删除成功,则返回true,如果删除失败,则返回false:
测试追加属性:通过 p 给 person 追加一个属性 sex,发现也能被set拦截捕获到:
如此,我们知道,Proxy中第二个参数配置对象中配置的get方法,是在读取p的属性时被拦截捕获;set方法,是在修改p的属性、或给p新增属性时被拦截捕获;而 deleteProperty 则是删除 p 的属性时被拦截捕获: