响应式原理
1:响应式函数的封装
1 //封装一个函数的响应式 2 //用数组来保存需要响应的函数 3 const reactiveFns = [] 4 //在watchFn里面的函数都会被监视 5 function watchFn(fn) { 6 reactiveFns.push(fn) 7 } 8 //对象的响应式 9 const obj = { 10 name: 'haha', 11 age: 20 12 } 13 watchFn(function() { 14 let newName = obj.name 15 console.log('哈哈哈哈哈', obj.name); 16 }) 17 watchFn(function() { 18 console.log(obj.name, 'demo function----'); 19 }) 20 21 function bar() { 22 console.log('普通的函数'); 23 24 } 25 obj.name = 'tyy' 26 //手动让响应式执行 27 reactiveFns.forEach(fn => fn())

2:响应式依赖的收集,如果只是把需要响应的放在一个类里面是补够的,每个属性的变化都应该有对应的响应式函数----这里可以设计一个类
1 //创建一个类 2 class Depend { 3 constructor() { 4 this.reactiveFns = [] 5 } 6 addDepend(reactiveFn) { 7 this.reactiveFns.push(reactiveFn) 8 } 9 notify() { 10 this.reactiveFns.forEach(fn => fn()) 11 } 12 } 13 //封装一个响应式函数 14 const depend = new Depend() 15 16 function watchFn(fn) { 17 depend.addDepend(fn) 18 } 19 //对象的响应式 20 const obj = { 21 name: 'haha', 22 age: 20 23 } 24 watchFn(function() { 25 let newName = obj.name 26 console.log('哈哈哈哈哈', obj.name); 27 }) 28 watchFn(function() { 29 console.log(obj.name, 'demo function----'); 30 }) 31 32 33 obj.name = 'tyy' 34 depend.notify()
和第一个一样的结果
3:自动监听对象变化 采用Proxy和Reflect自动监听属性变化
1 //创建一个类 2 class Depend { 3 constructor() { 4 this.reactiveFns = [] 5 } 6 addDepend(reactiveFn) { 7 this.reactiveFns.push(reactiveFn) 8 } 9 notify() { 10 this.reactiveFns.forEach(fn => fn()) 11 } 12 } 13 //封装一个响应式函数 14 const depend = new Depend() 15 16 function watchFn(fn) { 17 depend.addDepend(fn) 18 } 19 //对象的响应式 20 const obj = { 21 name: 'haha', 22 age: 20 23 } 24 //监听属性的变化 Proxy/Reflect 25 const objProxy = new Proxy(obj, { 26 get: function(target, key, receiver) { 27 return Reflect.get(target, key, receiver) 28 }, 29 set: function(target, key, newValue, receiver) { 30 Reflect.set(target, key, newValue, receiver) 31 depend.notify() 32 } 33 }) 34 35 watchFn(function() { 36 console.log('哈哈哈哈哈', objProxy.name); 37 }) 38 watchFn(function() { 39 console.log(objProxy.name, 'demo function----'); 40 }) 41 watchFn(function() { 42 console.log(objProxy.age, 'age变化需要执行的'); 43 }) 44 45 objProxy.name = 'tyy' 46 objProxy.age = 18

由图片可以看出来这个无论是那个属性发生变化,响应式的函数都会执行
4:依赖收集的管理
采用这种数据结构,利用map和weakMap来给每个属性构造depend

1 //创建一个类 2 class Depend { 3 constructor() { 4 this.reactiveFns = [] 5 } 6 addDepend(reactiveFn) { 7 this.reactiveFns.push(reactiveFn) 8 } 9 notify() { 10 this.reactiveFns.forEach(fn => fn()) 11 } 12 } 13 //封装一个depend 函数 14 const depend = new Depend() 15 function watchFn(fn) { 16 depend.addDepend(fn) 17 } 18 //封装一个获取depend函数 19 const targetMap = new WeakMap() 20 21 function getDepend(target, key) { 22 //通过target获取map对象 23 let map = targetMap.get(target) 24 if (!map) { 25 map = new Map() 26 targetMap.set(target, map) 27 } 28 let depend = map.get(key) 29 if (!depend) { 30 depend = new Depend() 31 map.set(key, depend) 32 } 33 return depend 34 } 35 36 37 //对象的响应式 38 const obj = { 39 name: 'haha', 40 age: 20 41 } 42 //监听属性的变化 Proxy/Reflect 43 const objProxy = new Proxy(obj, { 44 get: function(target, key, receiver) { 45 return Reflect.get(target, key, receiver) 46 }, 47 set: function(target, key, newValue, receiver) { 48 Reflect.set(target, key, newValue, receiver) 49 const depend = getDepend(target, key) 50 depend.notify() 51 } 52 }) 53 54 watchFn(function() { 55 console.log('哈哈哈哈哈', objProxy.name); 56 }) 57 watchFn(function() { 58 console.log(objProxy.name, 'demo function----'); 59 }) 60 watchFn(function() { 61 console.log(objProxy.age, 'age变化需要执行的'); 62 })
5:正确的函数依赖收集
上面我们都是采用watchFn来响应的,我们不能实现name响应name的函数,我们需要获取相应的depend 在get的时候把正确函数放在正确的依赖里面
1 //创建一个类 2 class Depend { 3 constructor() { 4 this.reactiveFns = [] 5 } 6 addDepend(reactiveFn) { 7 this.reactiveFns.push(reactiveFn) 8 } 9 notify() { 10 this.reactiveFns.forEach(fn => fn()) 11 } 12 } 13 //封装一个depend 函数 14 const depend = new Depend() 15 let globalfn = null 16 17 function watchFn(fn) { 18 globalfn = fn 19 fn() 20 globalfn = null 21 } 22 //封装一个获取depend函数 23 const targetMap = new WeakMap() 24 25 function getDepend(target, key) { 26 //通过target获取map对象 27 let map = targetMap.get(target) 28 if (!map) { 29 map = new Map() 30 targetMap.set(target, map) 31 } 32 let depend = map.get(key) 33 if (!depend) { 34 depend = new Depend() 35 map.set(key, depend) 36 } 37 return depend 38 } 39 40 41 //对象的响应式 42 const obj = { 43 name: 'haha', 44 age: 20 45 } 46 //监听属性的变化 Proxy/Reflect 47 const objProxy = new Proxy(obj, { 48 get: function(target, key, receiver) { 49 const depend = getDepend(target, key) 50 depend.addDepend(globalfn) 51 return Reflect.get(target, key, receiver) 52 53 }, 54 set: function(target, key, newValue, receiver) { 55 Reflect.set(target, key, newValue, receiver) 56 const depend = getDepend(target, key) 57 depend.notify() 58 } 59 }) 60 61 watchFn(function() { 62 console.log('哈哈哈哈哈', objProxy.name); 63 }) 64 watchFn(function() { 65 console.log(objProxy.name, 'demo function----'); 66 }) 67 watchFn(function() { 68 console.log(objProxy.age, 'age变化需要执行的'); 69 }) 70 console.log('name改变啦---------------------------'); 71 objProxy.name = 'tyy' 72 console.log('age改变啦--------------------------'); 73 objProxy.age = 20

6:depend的优化
使用set保存依赖函数 方式一个watchfn 里面多次调用同一个属性添加多次depend 注意,set中是add方法
1 //创建一个类 2 class Depend { 3 constructor() { 4 //防止adddepend方法重复 5 this.reactiveFns = new Set() 6 } 7 8 //让get里面更加简单 9 depend() { 10 if (globalfn) { 11 this.reactiveFns.add(globalfn) 12 } 13 } 14 notify() { 15 this.reactiveFns.forEach(fn => fn()) 16 } 17 } 18 //封装一个depend 函数 19 const depend = new Depend() 20 let globalfn = null 21 22 function watchFn(fn) { 23 globalfn = fn 24 fn() 25 globalfn = null 26 } 27 //封装一个获取depend函数 28 const targetMap = new WeakMap() 29 30 function getDepend(target, key) { 31 //通过target获取map对象 32 let map = targetMap.get(target) 33 if (!map) { 34 map = new Map() 35 targetMap.set(target, map) 36 } 37 let depend = map.get(key) 38 if (!depend) { 39 depend = new Depend() 40 map.set(key, depend) 41 } 42 return depend 43 } 44 45 46 //对象的响应式 47 const obj = { 48 name: 'haha', 49 age: 20 50 } 51 //监听属性的变化 Proxy/Reflect 52 const objProxy = new Proxy(obj, { 53 get: function(target, key, receiver) { 54 const depend = getDepend(target, key) 55 depend.depend() 56 return Reflect.get(target, key, receiver) 57 58 }, 59 set: function(target, key, newValue, receiver) { 60 Reflect.set(target, key, newValue, receiver) 61 const depend = getDepend(target, key) 62 depend.notify() 63 } 64 }) 65 //watchFn 66 67 watchFn(() => { 68 console.log(objProxy.name, '----------'); //get一次 adddepend就添加一次 69 console.log(objProxy.name, '++++++++++'); 70 }) 71 console.log('name改变啦---------------------------'); 72 objProxy.name = 'tyy'

7:对象的响应式操作vue2和vue3--------自动化对象响应 封装一个函数----把函数变成响应式函数
Vue3
1 //创建一个类 2 class Depend { 3 constructor() { 4 //防止adddepend方法重复 5 this.reactiveFns = new Set() 6 } 7 8 //让get里面更加简单 9 depend() { 10 if (globalfn) { 11 this.reactiveFns.add(globalfn) 12 } 13 } 14 notify() { 15 this.reactiveFns.forEach(fn => fn()) 16 } 17 } 18 //封装一个depend 函数 19 const depend = new Depend() 20 let globalfn = null 21 22 function watchFn(fn) { 23 globalfn = fn 24 fn() 25 globalfn = null 26 } 27 //封装一个获取depend函数 28 const targetMap = new WeakMap() 29 30 function getDepend(target, key) { 31 //通过target获取map对象 32 let map = targetMap.get(target) 33 if (!map) { 34 map = new Map() 35 targetMap.set(target, map) 36 } 37 let depend = map.get(key) 38 if (!depend) { 39 depend = new Depend() 40 map.set(key, depend) 41 } 42 return depend 43 } 44 45 46 //对象的响应式 47 const obj1 = { 48 name: 'haha', 49 age: 20 50 } 51 const objProxy = reactive(obj1) 52 //监听属性的变化 Proxy/Reflect 封装成把一个对象变成响应式的函数 53 function reactive(obj) { 54 return new Proxy(obj, { 55 get: function(target, key, receiver) { 56 const depend = getDepend(target, key) 57 depend.depend() 58 return Reflect.get(target, key, receiver) 59 60 }, 61 set: function(target, key, newValue, receiver) { 62 Reflect.set(target, key, newValue, receiver) 63 const depend = getDepend(target, key) 64 depend.notify() 65 } 66 }) 67 } 68 //watchFn 69 70 watchFn(() => { 71 console.log(objProxy.name, '----------'); //get一次 adddepend就添加一次 72 console.log(objProxy.name, '++++++++++'); 73 }) 74 const obj2 = reactive({ 75 mood: 'unhappy' 76 }) 77 watchFn(() => { 78 console.log(obj2.mood, 'obj2对象的响应式'); 79 }) 80 console.log('name改变啦---------------------------'); 81 objProxy.name = 'tyy' 82 console.log('mood改变啦---------------------------'); 83 obj2.mood = 'happy'

Vue2
1 //创建一个类 2 class Depend { 3 constructor() { 4 //防止adddepend方法重复 5 this.reactiveFns = new Set() 6 } 7 8 //让get里面更加简单 9 depend() { 10 if (globalfn) { 11 this.reactiveFns.add(globalfn) 12 } 13 } 14 notify() { 15 this.reactiveFns.forEach(fn => fn()) 16 } 17 } 18 //封装一个depend 函数 19 const depend = new Depend() 20 let globalfn = null 21 22 function watchFn(fn) { 23 globalfn = fn 24 fn() 25 globalfn = null 26 } 27 //封装一个获取depend函数 28 const targetMap = new WeakMap() 29 30 function getDepend(target, key) { 31 //通过target获取map对象 32 let map = targetMap.get(target) 33 if (!map) { 34 map = new Map() 35 targetMap.set(target, map) 36 } 37 let depend = map.get(key) 38 if (!depend) { 39 depend = new Depend() 40 map.set(key, depend) 41 } 42 return depend 43 } 44 45 46 //对象的响应式 47 const obj1 = { 48 name: 'haha', 49 age: 20 50 } 51 const objProxy = reactive(obj1) 52 //监听属性的变化 Proxy/Reflect 封装成把一个对象变成响应式的函数 53 function reactive(obj) { 54 Object.keys(obj).forEach(key => { 55 let value = obj[key] 56 Object.defineProperty(obj, key, { 57 get() { 58 const dep = getDepend(obj, key) 59 dep.depend() 60 return value 61 62 }, 63 set(newValue) { 64 const dep = getDepend(obj, key) 65 value = newValue 66 dep.notify() 67 } 68 }) 69 }) 70 return obj 71 } 72 //watchFn 73 74 watchFn(() => { 75 console.log(objProxy.name, '----------'); //get一次 adddepend就添加一次 76 console.log(objProxy.name, '++++++++++'); 77 }) 78 const obj2 = reactive({ 79 mood: 'unhappy' 80 }) 81 watchFn(() => { 82 console.log(obj2.mood, 'obj2对象的响应式'); 83 }) 84 console.log('name改变啦---------------------------'); 85 objProxy.name = 'tyy' 86 console.log('mood改变啦---------------------------'); 87 obj2.mood = 'happy'
和Vue3一样的结果

浙公网安备 33010602011771号