手撕ref
// 类似vue2中采用depend收集依赖 和 notify观察依赖
// 基本数据调用 const count = ref(0) ; effect(() => {console.log(123)}); count值发生改变,effect重新触发
let effective;
// 3依赖收集判断,有则添加进subs中,无则不操作
class Dep {
constructor() {
//2 收集数据 这里用set可以去重
this.subs = new Set();
}
// 1收集依赖
depend() {
// 6 如果有effective,则存入subs中,effective是一个函数,在触发监听时可遍历执行函数
if(effective) {
this.subs.add(effective)
}
}
// 1观察依赖,触发effect监听函数
notify() {
// 7 触发条件是在set函数中执行notify函数
this.subs.forEach(effect => effect())
}
}
// 1监听触发函数
function effect(fn){
//4 做一个判断标志,如果有fn才继续调用
effective = fn;
// 5 fn初始化会调用函数
fn();
}
// 1 创建ref函数,其中获取const count = ref(0), count.value++
function ref(val) {
let _value = val;
// 7 创建state,return state,
let state = {
get value() {
// 8 收集依赖,获取值
dep.depend();
return _value
},
set value(newValue) {
// 9 修改依赖,触发监听函数
_value = newValue;
dep.notify();
}
}
return state
}
// 6 实例化
const dep = new Dep()
// ---------------------------------------------------------------------------------------------------
const count = ref(0);
effect(() => {console.log(`触发监听${count.value}`)})
effect(() => {console.log(`另外的监听`)})
// 变化
setInterval(() => {
count.value++;
}, 2000)