vue3 组合式API与响应性的概念理解和简析

本文重点在概念的理解,而不在具体代码原理的实现

1. 组合式API简介

1.1. 组合式API是为了实现关注点抽离

1.1.1. 什么是关注点?

简单地可以这么理解,关注点就是代码业务逻辑,因为我们写代码的时候倾向于把特定的逻辑功能点聚合在一起,也就是我们倾向于“关注这些功能点”,因此关注点可以理解为特定的代码业务逻辑

1.1.2. 为什么需要关注点抽离?

关注点抽离也称为关注点分离,这里称为抽离是强调功能的抽取聚合而不与分散的概念混淆。关注点抽离也就是特定的代码功能块逻辑的抽离,更有利于程序的开发,问题的定位,以及功能的聚合等,试想一下,如果不同的功能代码,离散地分布在不同地方,如果想修改或调试代码,是不是很麻烦?

1.1.3. 组合式API是为了实现关注点抽离

vue3可以使用组合式API实现关注点抽离,换句话说,如果使用一般的vue构建组件的方式,可能实现不了关注点抽离的问题

因为普通的vue定义组件的方式,是通过data,computed,watch,methods,mouted等选项来完成的,而这些选项可以理解为框架性的功能选项,而不是跟业务功能相关的选项,如果一个组件涉及多个功能逻辑,那么可能就不得不把一个完整的业务功能点分散在这些选项之中了
组合式API的出现正是为了解决这种问题,熟悉react的同学大致也想到了,这就类似react已经实现了的hook

2. 组合式API

  • 2.1. 组合式API通过setup(){}选项暴露,该选项函数返回值可以在模板和实例中被访问,具体用法可参考官方文档:Setup
  • 2.2. 组合式API可以理解为关注点抽离的入口,我们可以把之前分散在各个选项data,computed,watch,methods,mouted的功能代码抽离到setup里面,然后暴露出来
  • 2.3. 组合式API可以抽离代码,意味着setup就不把data,computed,watch,methods,mouted这些功能作为选项了,但是如何实现与这些选项相匹配的功能呢?vue3为此暴露了与之匹配的ref,reactive,computed,watch,watchEffect等方法以及onMounted等生命周期
  • 2.4. 利用ref,reactive,computed等接口可以把之前分散在各个选项的逻辑功能块组合到一起,也就是,我们把之前分散的关注点抽离到一个代码块了,实现了关注点抽离
  • 2.5. 这会导致另外一个问题,关注点抽离到setup后,又通过setup暴露,后面setup本身的代码量是不是会越来越多,为了解决这个问题,又可以进一步把相同的功能代码抽离到一个单独的文件中,详见文档:什么是组合式 API

3. 响应性API

3.1. 响应性

所谓响应性,官方文档是这样解释的:响应性是一种允许我们以声明式的方式去适应变化的编程范例。简单地可以理解为,具有响应性的数据,如果在某处地方被使用,这个数据如果发生了变化,那么使用的地方也会相应更新

例如,有一个数据a,然后b使用了数据a,如果a在某处发生变化了,会触发b使用a的地方的更新。如果还不理解,再具体一点,vue data 选项里定义的就是响应性的数据,你在模板中使用了这些数据,然后这些数据在某处发生了变化,你模板里面的数据是不是也会相应更新?这就是响应性。vue3 通过 Proxy 和依赖&副作用收集 实现这种响应性,相比起vue3的Proxy,vue2是使用defineProperty实现的。

响应性原理可参照官方文档:响应性原理

3.2. 副作用

关于副作用,官方文档是这么描述的:Vue 通过一个副作用 (effect) 来跟踪当前正在运行的函数。副作用是一个函数的包裹器,在函数被调用之前就启动跟踪。Vue 知道哪个副作用在何时运行,并能在需要时再次执行它。

文档说得有点抽象,可以这么简单地理解,副作用就是记录[使用了响应式数据的地方]且可能需要被重新执行的一种机制,在vue3里面体现为一个函数包裹器,里面便包裹了使用了响应式数据的地方。也就是说,如果我们跟踪了副作用依赖于哪些响应式数据,在这些数据做出了变化之后,我们便可以触发副作用的执行,达到更新的目的。

你可以发现,其实computed,watch,甚至使用了数据的模板,都可以理解为跟副作用相关,因为他们都依赖于某些响应式的数据。

3.3. ref,reactive

ref,reactive可以创建响应式的数据,可以理解为setup里面与原来data选项相对应的功能,一旦有地方使用到了这些数据,就会被包裹进副作用里,并在这些数据修改的时候运行副作用更新,具体可参考官方文档:响应性基础

3.4. computed,watch,onMounted

onMounted对应原来的mouted周期钩子,更多周期钩子可见:生命周期钩子
computed,watch对应原来的computed,watch选项,其实质就是副作用,包裹了使用了响应式数据的内容,并在合适的时机更新他们,更多参考:响应式计算和侦听

4. 深入

看了上面的内容,可能有人会说,我现在知道响应性数据是什么,副作用是什么,但是从响应式数据的定义到使用的数据更新到底发生了什么,还是不太明白,要明白这个过程,就需要深入理解响应式数据是如何定义及使用的

4.1. Proxy

响应式数据的定义使用了ES6的Proxy,Proxy可以简单地理解为数据代理器,通过get和set方法,可以代理数据的获取和修改行为

4.2. get 和 set 方法

vue3的实现是,一个数据通过Proxy代理之后,在get方法里面,加入track方法,该方法追踪副作用的依赖,例如有一个computed返回的结果是this.a+this.b,那么这个this.a+this.b就被包裹进副作用内,而这个副作用被记录为依赖于a和b,因为在get a和b的时候,执行了track方法

而在set方法内,加入了trigger方法,该方法用于在响应式数据被修改后,执行依赖于这些数据的副作用,还是上面的computed例子,当this.a='newValue’重新设置后,被set方法拦截执行,set内部有trigger方法,该方法找到依赖于这些数据的副作用this.a+this.b并执行更新,这时候computed返回值就会更新

4.3. 万物皆可“副作用”

除了computed,像watch,引用数据的模板,其实都是跟副作用相关,原理跟上面描述的一致,只是computed和watch是更新数据,模板还需要通过数据的变化更新vnodes,最后再更新真实的dom
更多可参考官方文档:深入响应性原理

附:响应式数据与副作用示意图:
在这里插入图片描述

属于自己的文字,理解,观点,欢迎交流

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值