Skip to content
Preview
Preview

响应式简单实现

js
const isObject = v => v !== null && typeof v === 'object'

// Proxy
function reactive(obj) {
  if (!isObject(obj))
    return obj

  return new Proxy(obj, {
    get(target, key, receiver) {
      const ret = Reflect.get(target, key, receiver)

      console.log('获取', key)
      track(target, key)
      return isObject(ret) ? reactive(ret) : ret
    },
    set(target, key, value, receiver) {
      const ret = Reflect.set(target, key, value, receiver)

      console.log('设置', key)
      trigger(target, key)
      return ret
    },
    deleteProperty(target, key) {
      const ret = Reflect.deleteProperty(target, key)

      console.log('删除', key)
      trigger(target, key)
      return ret
    },
  })
}

// 声明一个响应函数,放入effectStack备用
const effectStack = []
function effect(fn) {
  const rxEffect = function () {
    // 1.捕获异常
    // 2.fn入栈出栈
    // 3.执行fn
    try {
      effectStack.push(rxEffect)
      return fn()
    }
    catch (error) {

    }
    finally {
      effectStack.pop()
    }
  }

  rxEffect()
  return rxEffect
}
// 响应函数触发某个响应式数据,开始依赖收集
const targetMap = new WeakMap()
function track(target, key) {
  const effect = effectStack[effectStack.length - 1]
  if (effect) {
    let depsMap = targetMap.get(target)
    if (!depsMap) {
      depsMap = new Map()
      targetMap.set(target, depsMap)
    }
    let deps = depsMap.get(key)
    if (!deps) {
      deps = new Set()
      depsMap.set(key, deps)
    }
    deps.add(effect)
  }
}
// setter或者deleteProperty触发时,根据映射关系执行对应的cb
function trigger(target, key) {
  const depsMap = targetMap.get(target)
  if (depsMap) {
    const deps = depsMap.get(key)
    if (deps) {
      deps.forEach((effect) => {
        effect()
      })
    }
  }
}

const state = reactive({ foo: 'foo' })

effect(() => {

  console.log('effect>>>', state.foo)
})

state.foo = 'fooooo'