VUE3 手撕ref和reative

399 阅读1分钟

手撕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)