Skip to content
js
/**
 * Depend类用于管理依赖关系和通知依赖更新
 */
class Depend {
  /**
   * 构造函数初始化依赖集合
   */
  constructor() {
    this.reactiveFns = new Set()
  }
  
  /**
   * 添加依赖函数
   */
  depend() {
    if (activeEffect) this.reactiveFns.add(activeEffect)
  }
  
  /**
   * 通知所有依赖函数更新
   */
  notify() {
    this.reactiveFns.forEach(fn => fn?.())
  }
}

/**
 * 当前活跃的Effect函数
 */
let activeEffect = null

/**
 * 监视Effect函数,执行并管理副作用更新
 * @param {Function} fn 要监视的Effect函数
 */
function watchEffect(fn) {
  activeEffect = fn
  fn()
  activeEffect = null
}

/**
 * 用于存储目标对象及其属性的依赖关系映射
 */
const targetMap = new WeakMap()

/**
 * 获取目标对象属性的依赖关系
 * @param {Object} target 目标对象
 * @param {string} key 目标对象的属性键
 * @returns {Depend} 依赖关系实例
 */
function getDep(target, key) {
  let depsMap = targetMap.get(target)
  if (!depsMap) {
    depsMap = new Map()
    targetMap.set(target, depsMap)
  }
  let dep = depsMap.get(key)
  if (!dep) {
    dep = new Depend()
    depsMap.set(key, dep)
  }
  return dep
}

/**
 * 创建响应式对象
 * @param {Object} obj 需要变成响应式的对象
 * @returns {Object} 响应式对象
 */
function reactive(obj) {
  return new Proxy(obj, {
    get(target, key, receiver) {
      const dep = getDep(target, key)
      dep.depend()
      return Reflect.get(target, key, receiver)
    },
    set(target, key, newValue, receiver) {
      Reflect.set(target, key, newValue, receiver)
      const dep = getDep(target, key)
      dep.notify()
    }
  })
}

// 创建两个响应式对象
const info = reactive({ name: 'jingyou',  age: 22 })
const info2 = reactive({ name: 'shihang',  age: 23 })

// 监视info和info2的name属性
watchEffect(() => {
  console.log(info.name)  // jingyou
})
watchEffect(() => {
  console.log(info2.name) // shihang
})
// 监视info的age和name属性, info2的age属性
watchEffect(() => {
  console.log(info.age, info2.age, info.name) // 22 23 jingyou
})

// 更新响应式对象的属性值
info.name = '荆友'  // 荆友 // 22 23 荆友
info2.name = '仕航' // 仕航
info.age = 24      // 24 23 荆友
info2.age = 25     // 24 25 荆友