读vue【深入响应式系统】后整理

一直以来对vue的依赖自动追踪的原理很感兴趣,像魔法一样。对于交给vue的对象返回后,在哪里使用了这个返回的对象vue会自动追踪,等这个对象改变时vue会自动通知到之前使用改变量的方法,整个过程和react很不一样,react的useEffect需要用户手动声明依赖而vue不同。

深入响应式系统这篇官方文档通俗易懂的介绍了vue的响应式原理,对文档中省略的部分补充后,文档中代码可以正常运行。阅读完文章后对其进行解释。

const reactiveObj = reactive({a: 1, b: 2})

whenDepsChange(() => {
  console.log(reactiveObj.a)
});

window.onclick = function() {
  reactiveObj.a += 1
}

当点击页面时会触发reactiveObj.a属性的修改,属性a修改后会自动通知到whenDepsChange重新执行。

  1. reactive会对入参的对象进行代理并返回新的代理对象,该代理对象监听每个属性的get和set,在属性被访问时对应的get方法会自动探测具体是哪个方法在读该属性,将方法和属性的关系存起来。
  2. whenDepsChange被执行时,会将入参的匿名函数设置到全局,例如变量activeEffect。执行whenDepsChange的匿名函数入参,在匿名函数中会读取属性a,属性aget方法会拿到全局的activeEffect(就是在读取属性a的匿名函数),将其和属性a关联起来。
  3. 点击window,设置属性a,执行其set方法,取出当时存的关联关系,更新属性后执行对应的函数。
let activeEffect = null

function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      track(target, key)
      return target[key]
    },
    set(target, key, value) {
      target[key] = value
      trigger(target, key)
    }
  })
}

function ref(value) {
  const refObject = {
    get value() {
      track(refObject, 'value')
      return value
    },
    set value(newValue) {
      value = newValue
      trigger(refObject, 'value')
    }
  }
  return refObject
}

const globalSubscribers = new WeakMap()

function getSubscribersForProperty(target, key) {
  if (!globalSubscribers.get(target)) {
    const map = new Map()
    globalSubscribers.set(target, map)
    map.set(key, new Set())
  }

  if (!globalSubscribers.get(target).get(key)) {
    const map = globalSubscribers.get(target)
    map.set(key, new Set())
  }

  return globalSubscribers.get(target).get(key)
}

function track(target, key) {
  if (activeEffect) {
    const effects = getSubscribersForProperty(target, key)
    effects.add(activeEffect)
  }
}

function trigger(target, key) {
  const effects = getSubscribersForProperty(target, key)

  effects.forEach(effect => effect())
}

function whenDepsChange(update) {
  const effect = () => {
    activeEffect = effect
    update()
    activeEffect = null
  }

  effect()
}

// 以下是用户可感知的
const reactiveObj = reactive({a: 1, b: 2})

whenDepsChange(() => {
  console.log(reactiveObj.a)
});

window.onclick = function() {
  reactiveObj.a += 1
}

参考

深入响应式系统

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值