使用方法

npm i @vue/reactivity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const {effect, reactive} = require('@vue/reactivity')

// 声明响应式变量
let a = reactive({
value: 10
})
let b;
effect(()=>{
b = a.value + 10
console.log(b)
// 默认执行一次
})
// 依赖值发生变化,关联值同步更新
a.value = 30

原理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
let currentEffect;
class Dep{
constructor(val){
this.effects = new Set()
this._val = val
}

get value(){
this.depend()②
return this._val
}
set value(newVal){
this._val = newVal
this.notice()②
}

// 1. 收集依赖
depend(){
if(currentEffect){
this.effects.add(currentEffect)
}
}

notice(){
this.effects.forEach(effect =>{
effect()
})
}
}
export function effectWatch(effect){
// 收集依赖
currentEffect = effect;
effect()
dep.depend();
currentEffect = null;
}

let dep = new Dep(10)
let b
effectWatch(()=>{
b = dep.value + 20
})
dep.value = 100
// dep.notice()①

② 为 ① 的优化

proxy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const targetMap = new Map()

function getDep(target, key){
let depsMap = targetMap.get(target)
!depsMap || (depsMap = new Map()) && targetMap.set(target, depsMap)
let dep = depsMap.get(key)
!dep || (dep = new Dep()) && depsMap.set(key, dep)
// key —— dep 映射
return dep
}

export function reactive(raw){
return new Proxy(raw, {
get(target, key){
console.log(key)
const dep = getDep(target, key)
// 依赖收集
dep.depend()
return Reflect.get(target, key) // target[key]
},
set(target, key, value){
const dep = getDep(target, key)
const result = Reflect.set(target, key, value)
dep.notice()
return result
}
})
}
const user = reactive({
age: 10
})
effectWatch(()=>{
// ,,,
})