# 什么是响应式
响应式就是在依赖数据的地方,当数据发生改变的时候,依赖数据的地方执行相应的方式进行响应。
# 如何成为响应式
使用proxy结合Reflect
什么是proxy和Reflect
let obj ={
age:1,
name:'a'
}
//receiver就是proxyObj
let proxyObj = new Proxy(obj,{
get:function(target,key,receiver){
console.log('---')
return Reflect.get(target,key,receiver)
},
set:function(target,key,val,receiver){
Reflect.set(target,key,val,receiver)
}
})
//测试
console.log(proxyObj.name)
// 'a'
// '---'
# 依赖收集的类
class Depend{
constructor(){
this.arr=[]
}
addDepend(sub) {
this.arr.push(sub)
}
notify(){
this.arr.forEach(item=>item())
}
}
# 依赖收集的管理
let weakMap = new WeakMap()
function getDepend(target,key){
let map = weakMap.get(target)
if(!map) {
map = new Map()
weakMap.set(target,map )
}
let dep = map.get(key)
if(!dep) {
dep = new Depend()
map.set(key,dep)
}
return dep;
}

# 完整demo
//1.收集依赖的depend类
class Depend{
constructor(){
this.arr=[]
}
addDepend(sub) {
this.arr.push(sub)
}
notify(){
this.arr.forEach(item=>item())
}
}
//2.全局变量,为了获取watchfn中正传入的fn,便于在get中获取。
let activeReactiveFn = null;
//3.vue3 依赖收集的数据结构,如上图所示。
let weakMap = new WeakMap()
//4.普通对象
let obj ={
age:1,
name:'a'
}
//5.代理对象,get set劫持。
let proxyObj = new Proxy(obj,{
get:function(target,key,receiver){
//
let dep = getDepend(target,key)
dep.addDepend(activeReactiveFn)
return Reflect.get(target,key,receiver)
},
set:function(target,key,val,receiver){
let dep = getDepend(target,key)
dep.notify()
Reflect.set(target,key,val,receiver)
}
})
//6.获取对象属性对应的depend。没有就创建。
function getDepend(target,key){
let map = weakMap.get(target)
if(!map) {
map = new Map()
weakMap.set(target,map )
}
let dep = map.get(key)
if(!dep) {
dep = new Depend()
map.set(key,dep)
}
return dep;
}
//7.函数首次执行会触发get.收集此时的fn在对应的depend中。
function watchFn(fn) {
activeReactiveFn = fn
fn()
activeReactiveFn = null
}
//8.正式测试
watchFn(function(){
console.log('1.用到了 obj的name会被收集',proxyObj.name);
})
watchFn(function(){
console.log('2.用到了 obj的name会被收集',proxyObj.name);
})
console.log('--------------set触发,回调重新执行-----------------');
proxyObj.name='我改了,回调要执行了'