Vue3响应式方案以及ref reactive的区别

本文深入探讨Vue3的响应式方案,包括ref和reactive的区别。Vue2中响应式依赖于Object.defineProperty,而Vue3采用Proxy和Reflect实现更强大的数据代理。文章详细解释了Proxy的拦截机制、Reflect的作用,以及reactive和createReactiveObject、mutableHandlers、mutableInstrumentations的关系。同时,介绍了ref的实现原理,包括createRef、toReactive和proxyRefs的功能。通过源码分析,揭示了ref在模板中如何自动脱ref的过程。
摘要由CSDN通过智能技术生成

一、前言

距离 Vue3 出来了已经有一段时间了, 最近呢重温了一下Vue3的响应式方案,以及ref reactive的区别,相信你看完本文,也能对 Vue3 响应式的了解有所提高

在看源码的过程中,时常会感到框架的设计之美,看起来也会感到赏心悦目, 这也是能坚持把源码看下去的动力

二、新的方案

1. 缘由

  • 已知在 Vue2 中, 响应式原理一直是采用 Object.defineProperty 来进行,那这样做有什么权限呢? 下面一一道来* 这个API, 只能拦截 get / set 的属性* 如对象 新增 或者 删除 了属性,则无法监听到改变* 对于数组,若使用数组的原生方法改变数组元素的时候 也无法监听到改变
  • 所以呢在Vue3中采用了 ProxyReflect搭配来代理数据2. Proxy 和 Reflect

1) Proxy

既然Vue3中响应式数据是基于 Proxy 实现的,那么什么是Proxy呢?

使用Proxy可以创建一个代理对象,它可以实现对 对象数据代理, 所以它 无法对非对象值进行代理,也就是为什么Vue3中对于非对象值要使用 ref 来进行响应式的原因 (后面讲解ref的时候再细说)

  • 代理是指 允许我们拦截并重新定义对一个对象的基本操作。 例如: 拦截读取、 修改等操作.
const obj = {}

const newP = new Proxy(obj, { // 拦截读取get(){/*...*/ },// 拦截设置属性操作set(){/*...*/ }
}) 

2) Reflect

说完了Proxy, 接下来我们来说说 Reflect

通过观察 MDN 官网可以发现, Reflect的方法Proxy的拦截器方法 名字基本一致

那就出现了一个问题,我们为什么要用 Reflect 呢

主要还是它的第三个参数,你可以理解为函数调用过程中的this,我们来看看它配合 Proxy 具体的用途吧

const obj = {foo: 1,// obj 中有一个 getter属性 通过this获取foo的值get getFoo() { return this.foo; }
};

const newP = new Proxy(obj,{// 拦截读取get(target, key) {console.log('读取', key); // 注意这里目前没有使用 Reflectreturn target[key];},// 拦截设置属性操作set(target, key, newVal) {console.log('修改', key);target[key] = newVal}})

obj.foo++
console.log(newP.getFoo); 

执行上面代码你会发现, 在 Proxy 中 get 拦截的中,只会触发对 getFoo 属性进行读取的拦截, 而无法触发在 getFoo 里面对 this.foo 进行读取的拦截!

问题就出现在 getFoo 这个getter里, 这里面的 this 在我们 未使用 Reflect 的时候指向它的原始对象,所以我们才无法通过 Proxy 拦截到属性读取

只需修改一下上面代码中 Proxy 里面的 get 拦截

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值