LOG // 058

vue3-reactive原理

ts
1// 代理简单类型,通过js对象访问器对对象的属性进行获取和设置
2const ref = (raw = null) => {
3  const r = {
4    // 对象的value属性获取
5    get value() {
6      track(r, 'value')
7      return raw
8    },
9    // 对象的value属性设置
10    set value(newVal) {
11      if (raw != newVal) {
12        raw = newVal
13        trigger(r, 'value')
14      }
15    }
16  }
17  return r
18}
19
20// 代理对象,在get,set方法中追踪属性和重新触发effect函数
21const reactive = (target) => {
22  return new Proxy(target, {
23    get (target, key, receiver) {
24      // const res = Reflect.get(target, key, receiver)
25      track(target, key)
26      return Reflect.get(target, key, receiver)
27    },
28    set (target, key, newVal, receiver) {
29      const oldVal = target[key]
30      const res = Reflect.set(target, key, newVal, receiver)
31      if (oldVal != newVal) {
32        trigger(target, key)
33      }
34      return res
35    }
36  })
37}
38
39let price = 1;
40let total = 1;
41
42let obj = reactive({
43  title: 'tttt',
44  num: 1,
45  child: {
46    title: 'ssss',
47    num: 2
48  }
49})
50
51let totalPrice = 0
52
53let text = ''
54
55// 存储每个属性对应的effect函数
56// const dep = new Set()
57
58// 存储所有 属性: effects  对象{ key: dep }
59// const depMap = new Map()
60
61// weakMap弱引用,其他对象不引用它,垃圾回收机制自动回收, key值只能是对象
62const targetMap = new WeakMap()
63
64let activeEffect = null
65
66const effect = (eff) => {
67  activeEffect = eff
68  activeEffect()
69  activeEffect = null
70}
71
72// 追踪属性
73const track = (target, key) => {
74  if (activeEffect) {
75    let depMap = targetMap.get(target)
76    if (!depMap) {
77      targetMap.set(target, depMap = new Map())
78    }
79    let dep = depMap.get(key)
80    if (!dep) {
81      depMap.set(key, dep = new Set())
82    }
83    dep.add(activeEffect)
84  }
85}
86
87// 触发重新执行effect函数
88const trigger = (target, key) => {
89  let depMap = targetMap.get(target)
90  if (!depMap) return
91  let dep = depMap.get(key)
92  if (dep) {
93    dep.forEach(effect => {
94      effect()
95    });
96  }
97}
98
99effect(() => {
100  text = obj.title + obj.num
101})
102
103console.log(text)
104
微信截图_20230505034100.png