class Dep {
// 依赖类,用来收集和触发
constructor() {
// 生成一个集合,用来存放依赖,之所以的用set是因为,set里的数组,数据不会重复
this.subscribers = new Set();
}
depend() {//收集
if (activeEffect) this.subscribers.add(activeEffect)
}
notify() {//触发
this.subscribers.forEach(effect => effect())
}
}
let activeEffect = null
function watchEffect(effect) {
activeEffect = effect
effect()
activeEffect = null
}
function reactive(obj){
Object.keys(obj).forEach(key=>{
let dep = new Dep()
let value = obj[key]
Object.defineProperty(obj,key,{
get(){
// 在get的时候,进行依赖收集
dep.depend()
return value
},
set(newValue){
// set赋值,并触发
value = newValue
dep.notify()
}
})
})
// 加工完成,返回
return obj
}
//测试代码
let person = reactive({age:18,name:"test"})
let school = reactive({name:"小黑学院"})
watchEffect(function(){
console.log(person.age,school);
})
watchEffect(function(){
console.log(person.name);
})
watchEffect(function(){
console.log(school.name);
})
// person.age = 20
school.name = "小白学院"
缺点,收集的依赖,在外面就拿不到了,只是做初步记录,做出以下修改就可完善一点,至少在外面可以拿到了
class Dep {
// 依赖类,用来收集和触发
constructor() {
// 生成一个集合,用来存放依赖,之所以的用set是因为,set里的数组,数据不会重复
this.subscribers = new Set();
}
depend() {//收集
if (activeEffect) this.subscribers.add(activeEffect)
}
notify() {//触发
this.subscribers.forEach(effect => effect())
}
}
let activeEffect = null
function watchEffect(effect) {
activeEffect = effect
effect()
activeEffect = null
}
// Map({key: value}): key是一个字符串,map强引用
// WeakMap({key(对象): value}): key是一个对象, 弱引用
const depMap = new WeakMap()//收集每个对象的key有哪些依赖===>{obj:{name:depClass}}
function getDep(obj,key){
let deps = depMap.get(obj)
if(!deps){
deps = new Map()
depMap.set(obj,deps)
}
let dep = deps.get(key)
if(!dep){
dep = new Dep()
deps.set(key,dep)
}
return dep
}
function reactive(obj){
Object.keys(obj).forEach(key=>{
let dep = getDep(obj,key)
let value = obj[key]
Object.defineProperty(obj,key,{
get(){
// 在get的时候,进行依赖收集
dep.depend()
return value
},
set(newValue){
// set赋值,并触发
value = newValue
dep.notify()
}
})
})
// 加工完成,返回
return obj
}
let person = reactive({age:18,name:"test"})
let school = reactive({name:"小黑学院"})
watchEffect(function(){
console.log(person.age,school);
})
watchEffect(function(){
console.log(person.name);
})
watchEffect(function(){
console.log(school.name);
})
// person.age = 20
school.name = "小白学院"
console.log(depMap);