目录

vue3学习笔记第144-146节reactive函数回顾vue2响应式原理vue3响应式原理_proxy

【vue3学习笔记】(第144-146节)reactive函数;回顾vue2响应式原理;vue3响应式原理_proxy

本篇内容对应课程第144-143节

课程 P144节 《reactive函数》笔记

https://i-blog.csdnimg.cn/blog_migrate/63b9ddaa6c2672bcd94b8b069a4e5271.png 验证 reactive 只能处理对象类型数据,不能处理基本类型数据:当使用reactive处理一个基本类型数据时,控制台直接报出了警告:reactive不能处理基本类型数据。 https://i-blog.csdnimg.cn/blog_migrate/d3c5ffb83a52bfeeb4c92b73121fdca2.png https://i-blog.csdnimg.cn/blog_migrate/5cdd2fdbfebf20b0cd5dbb42c5946ced.png 使用reactive定义对象类型数据,打印被reactive加工后的数据,发现原来的对象被reactive加工成了一个Proxy对象: https://i-blog.csdnimg.cn/blog_migrate/80cd34506c6ea0d344953c0021f0b9f2.png https://i-blog.csdnimg.cn/blog_migrate/5164c43b7b408099d19467dba6a8d5bd.png 对比之前用ref加工的对象类型数据,是一个 RefImpl 对象,里面的 value 属性是一个Proxy对象。ref在处理对象类型数据时,内部仍然是借助了 reactive 。 https://i-blog.csdnimg.cn/blog_migrate/11820fe4dc812248ea92dff50b3fda04.png https://i-blog.csdnimg.cn/blog_migrate/63d38a8fb6c2693d4c94a2cd80d1501a.png 验证 reactive 加工后的对象类型数据是否是深层次响应式的:结论是是深层次响应式的。 https://i-blog.csdnimg.cn/blog_migrate/68b1799e379f0acb3c95590c637231e3.png 验证 reactive 处理数组类型数据:发现可以直接通过数组索引去修改数据,且页面也可以捕获到数据的修改并更新视图。这在vue2中是不行的,需要借助一个方法 Vue.set 或 this.$set 来实现。 https://i-blog.csdnimg.cn/blog_migrate/567f614f0892d14fd33cbe7d73a86316.png https://i-blog.csdnimg.cn/blog_migrate/f68354656d24e86cefb38610ced7871d.png 总结: https://i-blog.csdnimg.cn/blog_migrate/f45c749cf8a0c758be30ebde60266c43.png

课程 P145节 《回顾vue2的响应式原理》笔记

先来回顾一下vue2中的响应式原理: 对象类型:通过 Object.defineProperty() 对属性的读取、修改进行拦截,也就是数据劫持。数据劫持是 响应式的根基,只有劫持到数据的改变,才可能实现响应式。 数组类型:当你调用数组的push方法时,其实调用的是vue经过二次封装的push方法,在这个方法里,vue做了两件事:一是帮你去正常地调用数组的push方法,二是去更新界面。 https://i-blog.csdnimg.cn/blog_migrate/7f964f37b8fd12ee9115a638f756b94d.png 在vue2中,直接给对象数据添加一个属性,以及删除一个已有属性,可以看到数据可以修改成功,但vue2监测不到数据的改变,不会进行视图更新。 只能通过 this.$set 或Vue.set 的形式去实现数据修改的同时更新视图。 https://i-blog.csdnimg.cn/blog_migrate/723d4dd59cf8c7393bcd2b63cd878a47.png https://i-blog.csdnimg.cn/blog_migrate/e8a4aa20f57d15d1d30ee1f5d53f64f9.png 在vue2中,通过数组下标的方式修改数组某一项的值,同样是数据已经改变但视图不会更新。通过 this.$set 或Vue.set 的方式或者调用数组的更新方法 splice 方法来达到更新视图的目的。 https://i-blog.csdnimg.cn/blog_migrate/80de1d8cb16e0f143c50510ba2b38ff9.png

课程 P146节 《vue3响应式原理》笔记

在vue3中,给响应式数据增加一个属性或删除一个已有属性,以及通过下标方式修改数组某一项(之前reactive一节已验证)数据都可以实现响应式,页面会更新。 https://i-blog.csdnimg.cn/blog_migrate/768c67b2f1e4a8988c17390f5a893713.png 模拟vue2中实现响应式: https://i-blog.csdnimg.cn/blog_migrate/61d4c4baafad7a4ca3e0b51c60942279.png 通过对象p修改属性,发现可以被监测到: https://i-blog.csdnimg.cn/blog_migrate/af607e4687ff1c8261df65995771a6c4.png https://i-blog.csdnimg.cn/blog_migrate/7889d0f2da4ece3f7171c72c1ddfd7ec.png 通过p对象添加一个属性,会发现新添加的属性与原有属性不同,它没有对应的getter和setter,只是一个普通的属性。 https://i-blog.csdnimg.cn/blog_migrate/d8bb9730a7e96dc8a9687279e6f4f2ca.png 通过p对象删除一个属性name,发现返回了一个false,同时发现p上面的name属性还在: https://i-blog.csdnimg.cn/blog_migrate/db5542d49fc77079ce691654b9cc1280.png 删不掉的原因是,在Object.defineProperty 中的配置中,没有加入 configurable:true : https://i-blog.csdnimg.cn/blog_migrate/f1d58dc193147b8a0022a68d3838ef83.png 模拟vue3中实现响应式:通过 new Proxy 得到一个代理对象,它接收两个参数,第一个为源对象,第二个参数是配置对象,如果不写任何配置,也必须要传递一个空对象,不允许不传递第二个参数: https://i-blog.csdnimg.cn/blog_migrate/cda94ab72a2ae5d7757027f8a82cae6d.png 输出代理对象p,可以看到它拥有与源对象相同的属性与值: https://i-blog.csdnimg.cn/blog_migrate/19a3d83d09caa8d2a4d1f88a371dbfcf.png 通过p对象修改、添加和删除属性,会发现源对象person上的相应属性也会被修改: https://i-blog.csdnimg.cn/blog_migrate/07a1d84dc75e30c9876325c5ce4ba191.png 为了让修改数据时可以被监测到,我们在 new Proxy 的第二个参数配置对象中添加一些配置:get函数和set函数: https://i-blog.csdnimg.cn/blog_migrate/9b79e8e55bfb589620088abe93320784.png 此时再次通过p对象修改属性,可以被监测到了: https://i-blog.csdnimg.cn/blog_migrate/78046e830db478dfb56a04f2816b31bc.png 为了使删除属性时也被监测到,增加 deleteProperty 配置,在这个配置中,需要用 delete 关键字真正删掉操作删除的属性: https://i-blog.csdnimg.cn/blog_migrate/fd81db046230427c6d98131932889702.png 测试删除属性:当删除p身上的name后,删除的动作被监测到了,同时 person 和 p 身上的name属性都被删除掉了。删除语句执行后返回了一个false: https://i-blog.csdnimg.cn/blog_migrate/a2d1a5067d5e5a911c5bf7112a855fcd.png 这是因为绿色框的代码, deleteProperty 方法没有返回值,相当于返回了 undefined,也就是 false: https://i-blog.csdnimg.cn/blog_migrate/602b321d4b23b62b49d9077c55ba2a44.png 给 deleteProperty 方法设置返回值: https://i-blog.csdnimg.cn/blog_migrate/a7601ac8070938b9bfd1035566a0b1ab.png 此时再次执行删除属性操作,就会返回删除结果了,如果删除成功,则返回true,如果删除失败,则返回false: https://i-blog.csdnimg.cn/blog_migrate/1505c2a1852bf67630c31600933a5ee0.png 测试追加属性:通过 p 给 person 追加一个属性 sex,发现也能被set拦截捕获到: https://i-blog.csdnimg.cn/blog_migrate/61a713b92fe6498756f0690c4b6e0a57.png 如此,我们知道,Proxy中第二个参数配置对象中配置的get方法,是在读取p的属性时被拦截捕获;set方法,是在修改p的属性、或给p新增属性时被拦截捕获;而 deleteProperty 则是删除 p 的属性时被拦截捕获: https://i-blog.csdnimg.cn/blog_migrate/9dee4ae5f80203977daff94f5593ff11.png