浅谈 vue3 响应式原理 第一篇 响应式和副作用

浅谈 vue3 响应式原理 第一篇 响应式和副作用

一年前,在开课吧的视频里看到 winter、大圣还有尤大吹嘘着 vue3,各种新名词映入眼帘:watchEffect,reactive,ref,当时觉得好牛逼啊,一定要学一下(咕咕咕)。

一年后,watchEffect 是啥,reactive 是啥,ref 又是啥,怎么多了出了这么多东西,好难啊,趁现在赶紧摸索清楚。

副作用

我们经常能在尤大口中听到一个词: sideEffect。首次听这个词时,我也是一头雾水,副作用到底是什么,吃药时的副作用吗?在尤大在评论 winter 的小案例时,他讲了 winter 在组件销毁时没有清理掉之前设置的事件监听器,这会对程序产生副作用。当然,尤大此时说的是 sideEffect 是另一个方面的。

vue3中的 sideEffect 怎么理解?一些变量执行某些基本操作时,被拦截并执行一些事情,这些事情叫 sideEffect

拦截

上面说到拦截,这是 vue 经常做的事情。vue 就喜欢在变量读取、写入的时候拦截并做操作。

在 vue2 中,尤大是通过 Object.defineProperty 给变量设置存取器属性,然后在存取器中执行副作用。到了 vue3,尤大用了 es6 的新特性 ProxyReflect 重写了这部分的代码。Proxy 提供了对变量基本操作的各种拦截回调,Reflect 则是对这些基本操作的实现。通过 Proxy,将变量的基本操作修改为副作用+基本操作,完成副作用的执行。

响应式

响应式是什么

要明白响应式是什么,我们通过下面几行代码讲解

1
2
3
4
5
6
7
8
let product = {
price:10,
quantity:2
}
let total = 0
total = product.price * product.quantity //20
product.quantity = 3
total //20

上面代码表明了 total 是由 price 和 quantity 计算得出,但是当我们修改了 quantity 后,total 的值却没有跟着变,因此我们知道原生的 javascript 是没有响应式的

那么要怎么实现响应式

1
2
3
4
5
6
7
8
9
10
11
12
13
let product = {
price:10,
quantity:2
}
let total = 0
function trigger(){
total = product.price * product.quantity
}
trigger()
total //20
product.quantity = 3
trigger()
total //30

我们发现,如果我们将 total 的计算方式保存为一个函数,然后在每次更新 quantity 之后调用一次,total 的值就会跟着变化。

那么只要我们在quantity更新时自动执行 trigger,响应式就实现了。

自动?

要实现自动,我们就需要前面讲到的知识:拦截

我们通过 Proxy,在 quantity 执行 set 操作时进行拦截,然后将上述 trigger 添加为 set 操作的副作用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let p = {
price:10,
quantity:2
}
let total = 0
function trigger(){
total = p.price * p.quantity
}
let product = new Proxy(p,{
set(target:any,key:string,value:any,receiver:any){
let result = Reflect.set(target,key,value,receiver)
trigger()
return result
}
})
trigger()
total//20
product.quantity = 3
total//30

这下我们可以在 set 操作时自动执行 trigger

未完持续O(∩_∩)O