前置
vue2的响应式原理
它只能监听指定对象的、指定属性的 getter 和 setter。所以当对象或数组新增属性时,vue2无法为新增的属性增加响应性。
| 12
 3
 4
 
 | Object.defineProperty(target, key, {set(newVal) {},
 get(key) {}
 })
 
 | 
vue3的响应式系统
reactive
简单实现reactive,核心有几部分
effect:响应式的依赖收集和触发的机制的体现
reactive函数:提供出去要使用的函数
track:收集/追踪依赖
trigger:触发依赖
| 12
 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
 45
 46
 47
 48
 49
 50
 51
 52
 53
 
 | let activeEffect = null
 class reactiveEffect {
 constructor(fn) {
 this.fn = fn
 }
 run() {
 activeEffect = this
 return this.fn()
 }
 }
 const effect = (fn) => {
 const re = new reactiveEffect(fn)
 re.run()
 }
 
 
 function reactiveFn(target) {
 return new Proxy(target, {
 get(target, key, receiver) {
 track(target, key)
 return target[key]
 },
 set(target, key, value, receiver) {
 target[key] = value
 trigger(target, key)
 }
 })
 }
 
 
 function track(target, key) {
 if (!activeEffect) return
 let depsMap = targetMap.get(target)
 if (!depsMap) {
 targetMap.set(target, (depsMap = new Map()))
 }
 let dep = depsMap.get(key)
 if (!dep) {
 depsMap.set(key, (dep = new Set()))
 }
 dep.add(activeEffect)
 }
 
 
 function trigger(target, key) {
 let depsMap = targetMap.get(target)
 if (!depsMap) return
 const dep = depsMap.get(key)
 if (dep) dep.forEach(eff => {
 eff.fn()
 })
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | const student = {
 name: 'Adam',
 age: '18'
 }
 const proxyStudent = reactiveFn(student)
 effect(() => {
 document.querySelector('.wrap').innerHTML = proxyStudent.name + proxyStudent.age
 })
 proxyStudent.age = 19
 
 | 
ref
reactive 只能构建复杂数据类型的响应性,proxy就是这样。vue为我们提供了ref来解决这个问题。比较不熟悉的是 gett和set 
- ref 方法:接收任意数据
- ref 方法:生成RefC实例,并进行返回
- ref 方法:利用 get 和set 监听- getter、setter行为,以便执行依赖收集和依赖触发
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | class RefC {constructor(value) {
 this._value = value
 }
 
 get value() {
 if (activeEffect) {
 console.error('reffff', ref)
 const dep = ref.dep || (ref.dep = new Set())
 dep.add(activeEffect)
 }
 return this._value
 }
 
 set value(newVal) {
 this._value = newVal
 if (ref.dep) ref.dep.forEach(eff => eff.fn())
 }
 }
 
 function ref(value) {
 return new RefC(value)
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 
 | const v = '小明'
 const refVar = ref(v)
 effect(() => {
 document.querySelector('.wrap').innerHTML = refVar.value
 })
 refVar.value = '小红'
 
 | 
参考链接
https://juejin.cn/post/7186248802423013432
编译时、运行时的源码解析:
https://blog.csdn.net/qq_34618600/article/details/140893125