vue3-reactive

35 阅读1分钟

reactive

var isType = (target, type) => Object.prototype.toString.call('').replace(/\[\w+\s(\w+)\]/g, '$1').toLowerCase().includes(type.toLowerCase())
var reactive = function (target) {
  return new Proxy(target, {
    get (target, key, recevier) {
      const value = Reflect.get(target, key, recevier)
      track(target, key)
      if (isType(value, 'object')) {
          return reactive(value)
      }
      return value
    },
    
    set (target, key, value, recevier) {
      const bool = Reflect.set(target, key, value, recevier)
      trigger(target, key)
      return bool
    }
  })
}
var activeEffect
var effect = function(fn) {
  const _effect = function() {
    activeEffect = _effect
    fn()
  }
  _effect()
}
// 扁平来看就是targetMap->depsMap->deps->activeEffect
var targetMap = new WeakMap()

var track = function(target, key) {
  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(activeEffect)
}



var trigger = function(target, key) {
  let depsMap = targetMap.get(target)
  let deps = depsMap.get(key)
  deps.forEach((effect) => effect())
}

USE

```js
const obj = reactive({
    name: '李四',
    age: '20'
})


effect(() => {
    document.body.innerHTML = obj.name + '-' obj.age
})


obj.age++