Vue3 Reactive响应式原理逻辑详解

 更新时间:2022年07月03日 10:03:44   作者:​ Liqiuyue   ​  
这篇文章主要介绍了Vue3 Reactive响应式原理逻辑详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下

前言

本篇文章主要讲解vue响应式原理的逻辑,也就是vue怎么从最开始一步步推导出响应式的结构框架。 先从头构建一个简单函数推导出Vue3的Reactive原理,最后再进行源码的验证。

一、怎么实现变量变化

怎么实现变量变化,相关依赖的结果也跟着变化

 当原本price=5变为price=20total应该变为40,但是实际total并不会改变。 解决办法可以这样,当变量改变了,重新计算一次,那么结果就会改变为最新的结果。

如果需要重新计算,我们需要将total语句存储为一个函数,才能实现依赖的变量改变就进行一次依赖项计算。这里就用effect表示函数名。

来,试一下:

 👌,实现了变量price改变,依赖变量price quantity的变量total也发生改变。

下一步,我们要解决的问题是:应该怎么把effect存储起来,让代码更加有通用性,而不是一直复写effect,分离出其他的功能的函数各司其职,也就是大家常说的解耦

二、怎么实现变量变化

怎么实现变量变化,变量改变后就取出effect执行

用什么存储effect呢?当然是用Set,因为Set会过滤出重复的元素,所以能够保证存储在Set中的函数不是重复的。 这里定义一个存储effect依赖的变量为dep = new Set(),定义track函数表示存储的过程。 定义trigger函数用以取出dep中相关的effect函数执行(这里定义的函数与Vue3源码同名同意义)。

  • effect: 会影响结果的函数(要实现响应式的依赖语句)
  • track:保存所有的effect
  • trigger: 当变量改变重新执行代码

 👌,解耦之后代码结构更清晰了。

下面需要解决的一个问题:一个object通常有多个属性,比如product = { price: 5, quantity: 2 },在保存依赖时只创建了一个dep的集合,应该给pricequantity都创建dep,因为total的最终结果依赖这两个属性,其中任何一个改变都要触发trigger函数。创建了两个dep就需要一个容器将dep存储起来。

三、将多个dep存储在Map中

因为不同的属性名有自己对应的dep,所以我们用Map结构(键值对形式)来保存不同dep

 👌,一个object的多个属性依赖问题解决,更具有通用性了。

下一个问题是:不可能只有一个对象,多个对象又怎么办?let product = { price: 5, quantity: 2 } let user = { firstName: "Joe", lastName: "Smith" },比如两个对象的时候就需要进一步修改上面的代码了。

四、将多个object的depsMap继续存储起来

这里用WeakMap数据结构去存储多个需要响应式的object的depsMapWeakMap的基本使用和Map差不多,只不过WeakMap只接受对象为键值,而depsMap是一个Map结构刚好(必须是)是对象类型。targetMap作为存储多个depsMap的容器名。

👌,到这里已经基本实现了通用性的响应式代码了,但是还有最后一个问题就是:我们的代码都需要手动执行(自己添加trigger运行),不能自动运行。怎么让它能够自动检测变量改变,然后自动修改结果呢?

五、核心

通过Reflect和Proxy解决自执行问题

在JavaScript中,自动检测变量不就是get、自动修改变量不就是set吗?在Vue2.x版本中用ES5的Obeject.defineProperty()自带的getter/setter去解决这个问题。ES6中Proxy也能解决这个问题,但是Proxy不兼任IE浏览器,当时大家还讨论过说不知道尤大怎么去考虑这个问题,现在问题的答案就是——不考虑。也就是根本不考虑IE兼不兼容🐮🍺。

Proxy就是代理的意思,任何对真实数据的操作它都能拦截并且代理操作,也就是说Object上一些能实现的方法,Proxy也能实现。Proxy使用语法是new Proxy(target, hanler)handler是你想实现什么样的代理功能配置。 而Reflect就更神奇了,它的作用是取代Object类上的一些方法让Obeject类更纯粹的代表一个类,不要附加太多方法在上面,比如a in obj表示判断obj中是否有a,在Reflect中用Reflect.has(a)比较语义化的方式就可以代替之前的方法。

正是因为这样,ProxyReflect就对应上了,都有Object上的方法。

稍微封装一下我们的函数,名叫Reactive

 👌,至此,Vue3基本的响应式原理就解析完了。

六、源码解析(TypeScript)

 returncreateReactiveObject函数,所以去看createReactiveObject

 前面的代码都是判断各种情况,我们就看最后几行

const observed = new Proxy(
    target,
    collectionTypes.has(target.constructor) ? collectionHandlers : baseHandlers
  )

可以看到ProxyhandlercollectionHandlers或者 baseHandlers,继续选择一个看一看。

在 baseHandlers中可以看到导出了get/set/deleteProperty等属性配置:

我们看一下set

 和我们之前的逻辑差不多,只不过真正实现就很复杂,因为有很多复杂条件需要去处理。

其他的get等方法也一样,做了很多条件判断处理,完善了每一种会出现的情况。

到此这篇关于Vue3 Reactive响应式原理逻辑详解的文章就介绍到这了,更多相关Vue3 Reactive响应式 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue-element-admin配置小结

    vue-element-admin配置小结

    本文主要介绍了vue-element-admin配置小结,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • vuejs 动态添加input框的实例讲解

    vuejs 动态添加input框的实例讲解

    今天小编就为大家分享一篇vuejs 动态添加input框的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • Vue2的路由和异步请求方式

    Vue2的路由和异步请求方式

    这篇文章主要介绍了Vue2的路由和异步请求方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • 详解用vue.js和laravel实现微信支付

    详解用vue.js和laravel实现微信支付

    本篇文章主要介绍了用vue.js和laravel实现微信支付,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • Vue中watch监听属性新旧值相同的问题解决方案

    Vue中watch监听属性新旧值相同的问题解决方案

    这篇文章主要给大家分享了Vue中watch监听属性新旧值相同问题解决方案,如果有遇到相同问题的朋友,可以参考阅读本文
    2023-08-08
  • vue2手机APP项目添加开屏广告或者闪屏广告

    vue2手机APP项目添加开屏广告或者闪屏广告

    这篇文章主要为大家详细介绍了vue2手机APP项目添加开屏广告或者闪屏广告的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • 使用vue深度选择器修改ElementUI组件内样式的示例代码

    使用vue深度选择器修改ElementUI组件内样式的示例代码

    在带有scoped属性的style中书写样式时,无法作用影响到子组件中的样式,此时我们会使用到deep深度选择器,来解决此问题,我们在使用less预处理器,能正常使用,但是在scss预处理器中会报错,下面通过本文介绍vue深度选择器修改ElementUI组件内样式,需要的朋友可以参考下
    2022-12-12
  • vue3中nextTick()应用实例详解

    vue3中nextTick()应用实例详解

    这篇文章主要给大家介绍了关于vue3中nextTick()应用的相关资料,nextTick()等待下一次DOM更新刷新的工具方法,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-12-12
  • vue如何通过ref调用router-view子组件的方法

    vue如何通过ref调用router-view子组件的方法

    这篇文章主要介绍了vue 通过ref调用router-view子组件的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2023-11-11
  • VUEJS实战之利用laypage插件实现分页(3)

    VUEJS实战之利用laypage插件实现分页(3)

    这篇文章主要为大家详细介绍了VUEJS实战之修复错误并且美化时间,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-06-06

最新评论