加入收藏 | 设为首页 | 会员中心 | 我要投稿 天瑞地安资讯网 (https://www.ruian888.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 云计算 > 正文

Vue3侦听器的实现原理是什么

发布时间:2022-09-16 12:39:17 所属栏目:云计算 来源:
导读:  这篇文章主要讲解了“Vue3侦听器的实现原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Vue3侦听器的实现原理是什么”吧!
  这篇文章主要讲解了“Vue3侦听器的实现原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Vue3侦听器的实现原理是什么”吧!
 
  侦听响应式对象
 
  前面我们聊到计算属性,它可以自动计算并缓存响应式数据的值。而如果我们仅需要在响应式数据变化时,执行一些预设的操作云计算原理,就可以使用watch侦听器。我们还是先来实现一个最简单的例子,然后来一点一点扩充它。
 
  const?data?=?{foo:?1}
 
  const?obj?=?reactive(data)
 
  watch(obj,?()?=>?{
 
  ??console.log('obj已改变')
 
  })
 
  在这个例子中,我们使用了watch侦听器,当obj的属性被改变时,控制台应该会打印出obj已改变。基于前面我们对计算属性的实现,这里我们已经有了一个大概的思路。把watch视为响应式对象的副作用函数,当响应式对象改变时,触发执行该副作用函数。
 
  想要触发副作用函数,必须先收集它,还记得副作用函数是如何收集的吗?对,当响应式数据被get时,收集副作用函数。所以首先,我们需要让watch被响应式对象收集到。
 
  function?watch(getter,?cb)?{
 
  ??effect(
 
  ????()?=>?getter.foo
 
  ??)
 
  }
 
  接着,我们还需要让我们预设的方法被执行。当响应式数据被set时,触发副作用函数。这里我们想触发的是cb这个传入的回调函数,这里我们就又能用到实现计算属性时的调度器了,当调度器存在时,set触发的trigger会先执行调度器中的函数。
 
  function?watch(getter,?cb)?{
 
  ??effect(
 
  ????()?=>?getter.foo,
 
  ????{
 
  ??????scheduler()?{
 
  ????????cb()
 
  ??????}
 
  ????}
 
  ??)
 
  }
 
  Vue3侦听器的实现原理是什么
 
  一个简单的侦听器已经完成了!这里我们为了简单,把功能写死了,仅支持对obj.foo的侦听。接下来,我们就要想想,如何实现对响应式对象的任意属性进行侦听?
 
  按照前面的思路,想要实现对响应式对象的任意属性的侦听,就需要我们get到该对象的每一个属性,这就需要我们对响应式对象进行一次递归遍历。
 
  function?traverse(value,?seen?=?new?Set())?{?//?(1)
 
  ??if(typeof?value?!==?'object'?||?value?===?null?||?seen.has(value))?return
 
  ??seen.add(value)
 
  ??for(const?key?in?value)?{
 
  ????traverse(value[key],?seen)
 
  ??}
 
  ??return?value
 
  }
 
  为了避免递归遍历对象时,循环引用造成的死循环,我们在(1)处创建了Set,当重复出现相同的对象时,直接返回。
 
  侦听属性值
 
  在Vue3中,我们不能直接侦听响应式对象的属性值。如果需要侦听响应式对象的属性值,就需要一个getter函数,让侦听器能被响应式对象收集到。
 
  const?data?=?{
 
  ??foo:?1
 
  }
 
  const?obj?=?reactive(data)
 
  watch(
 
  ??()?=>?obj.foo,?
 
  ??()?=>?{
 
  ??console.log('obj.foo已改变')
 
  })
 
  指定了属性就意味着,当前的侦听器仅会被指定的属性触发,就无需递归遍历整个响应式对象了。
 
  function?watch(getter,?cb)?{
 
  ??if(typeof?getter?!==?'function')?getter?=?traverse(getter)?//?(2)
 
  ??effect(
 
  ????()?=>?getter(),
 
  ????{
 
  ??????scheduler()?{
 
  ????????cb()
 
  ??????}
 
  ????}
 
  ??)
 
  }
 
  Vue3侦听器的实现原理是什么
 
  在(2)处,我们增加了一个判断,如果传入的已经是getter函数,我们直接使用,如果不是getter函数,则认为是一个响应式对象,就需要进行递归遍历。
 
  侦听获取新值和旧值
 
  在Vue中我们还需要能够在回调函数cb()中拿到响应式数据更新前后的新值与旧值。
 
  const?data?=?{
 
  ??foo:?1
 
  }
 
  const?obj?=?reactive(data)
 
  watch(
 
  ??()?=>?obj.foo,?
 
  ??(newValue,?oldValue)?=>?{
 
  ??console.log(newValue,?oldValue)
 
  })
 
  接下来的问题是,如何获取newValue与oldValue。newValue好解决,执行完回调函数cb()得到的就是newValue,但这里如何获取oldValue的值呢?要从watch中拿到旧值,那就不能让副作用函数被立即执行。这里想到了什么?对,在实现计算属性的时候,我们用到过的lazy,它可以禁止副作用函数自动执行。
 
  function?watch(getter,?cb)?{
 
  ??if(typeof?getter?!==?'function')?getter?=?traverse(getter)
 
  ??let?oldValue
 
  ??const?effectFn?=?effect(
 
  ????()?=>?getter(),
 
  ????{
 
  ??????lazy:?true,?//?(3)
 
  ??????scheduler()?{
 
  ??????????cb(oldValue)
 
  ??????}
 
  ????}
 
  ??)
 
  ??oldValue?=?effectFn()?//?(4)
 
  }
 
  云计算原理与范式_云计算为什么叫云计算_云计算原理
 
  在(3)处我们设置了lazy开关,设置了lazy后,副作用函数的执行权就交到了我们自己手上。在(4)处,我们手动执行了副作用函数。这里可以需要我们向前回顾一下,前面我们传入的getter是一个函数() => obj.foo,而effect函数的第一个参数就是真正被执行的副作用函数,所以我们手动执行的,其实就是函数() => obj.foo,这样我们就拿到了旧值。
 
  如何获取新值呢?在响应式数据的值更新后,副作用函数effect会被触发执行,当调度器属性存在时,执行调度器。在调度器中,我们可以再次执行副作用函数,通过() => obj.foo拿到改变后的新值。
 
  在(5)处,执行完回调函数cb(),我们进行了一下善后工作,更新了oldValue的值,为下一次回调做准备。
 
  Vue3侦听器的实现原理是什么
 
  有时,我们还希望侦听器可以在创建时就立即执行回调函数。
 
  const?data?=?{
 
  ??foo:?1
 
  }
 
  const?obj?=?reactive(data)
 
  watch(
 
  ??()?=>?obj.foo,?
 
  ??(newValue,?oldValue)?=>?{
 
  ??????console.log('newValue:',?newValue,',?oldValue:',?oldValue)
 
  ??},
 
  ??{?immediate:?true?}
 
  )
 
  当immediate的值为true时,需要立即执行。明确了需求,我们来完善watch侦听器。
 
  function?watch(getter,?cb,?options?=?{})?{
 
  ??if(typeof?getter?!==?'function')?getter?=?traverse(getter)
 
  ??let?oldValue,?newValue
 
  ??function?job()?{?//?(6)
 
  ????newValue?=?effectFn()
 
  ????cb(newValue,?oldValue)
 
  ????oldValue?=?newValue
 
  ??}
 
  ??const?effectFn?=?effect(
 
  ????()?=>?getter(),
 
  ????{
 
  ??????lazy:?true,
 
  ??????scheduler:?job,
 
  ????}
 
  ??)
 
  ??if(options.immediate)?{??//?(7)
 
  ????job()
 
  ??}?else?{
 
  ????oldValue?=?effectFn()
 
  ??}?
 
  }
 
  在(6)处,我们抽离了回调函数的执行逻辑,当options.immediate存在时,直接触发执行。
 
  感谢各位的阅读,以上就是“Vue3侦听器的实现原理是什么”的内容了,经过本文的学习后,相信大家对Vue3侦听器的实现原理是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。
 
 

(编辑:天瑞地安资讯网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!