【Vue3响应式原理#01】Reactivity

这篇具有很好参考价值的文章主要介绍了【Vue3响应式原理#01】Reactivity。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

专栏分享:vue2源码专栏,vue3源码专栏,vue router源码专栏,玩具项目专栏,硬核💪推荐🙌

欢迎各位ITer关注点赞收藏🌸🌸🌸

背景

以下是柏成根据Vue3官方课程整理的响应式书面文档 - 第一节,课程链接在此:Vue 3 Reactivity - Vue 3 Reactivity | Vue Mastery,本文档可作为课程的辅助材料,配合食用,快乐双倍!

我们先来看一下这个简单的Vue应用程序,Ok!如果我们加载了这个组件,然后我们的价格price发生了改变,Vue是如何知道更新模版内容的呢?接下来,我们将会用 Vue3 建造响应式的方法,从头开始制造一个响应式引擎,让我们一步一步的来解决这个问题!

【Vue3响应式原理#01】Reactivity

dep

How can we save the total calculation, so we can run it agine when price or quantity updates ?

如何存储 total 的计算方式,当 price 或 quantities 更新时,total 再计算一次?

我们想将下面这段代码存储在某种储藏室中,然后我们需要运行它,之后我们还想再次运行这个被存储的代码【被存储可能有多种功能代码】

let total = price * quantity

让我们来实现一下,下面所列举的effect()track()trigger()你都可以在 Vue3 响应性源码中看到同名的函数。

  • dep:一个 Set 对象,存储我们的effects,或者说是一个effect集(Set)。我们在这里使用 Set 的原因是 Set 不允许出现重复值,当我们尝试添加同样的effect时,它不会变成 Set 集合的两个子成员
  • effect():一个方法,包含了我们想要存储的代码
  • track():一个方法,使用dep变量去保存effect
  • trigger():一个方法,遍历dep去运行我们存储的所有代码

【Vue3响应式原理#01】Reactivity

depsMap

Often our objects will have multiple properties and each property will need their own dep. How can we store these ?

通常,我们的对象会有多个属性,每个属性都需要自己的 Dep(依赖关系),或者说 effect 的 Set 集合,那么,我们如何存储,或者说怎样才能让每个属性都拥有自己的依赖呢?

我们现在拥有一个product对象,其每一个属性都需要有自己的dep。【dep其实就是一个effect集(Set),这个 effect集应该在值发生改变时重新运行。】

正如我们看到的,dep的类型是 Set,Set 中的每个值都只是一个我们需要执行的effect,就像我们这个计算total的匿名函数。要把这些dep存储起来,且方便我们以后在找到他们,我们要创建一个depsMap

  • depsMap: 一个 Map 对象,存储了每个属性到其自己依赖dep对象的映射;每一个属性都拥有它们自己的,可以重新运行effectdep;我们使用对象属性名作为键,比如pricequantity,值是一个depeffect集】

【Vue3响应式原理#01】Reactivity

让我们来实现一下,代码如下:

<html>
  <head></head>
  <body>
    <div id="app">
      <div>depsMap</div>
    </div>
  </body>
  <script>
    const depsMap = new Map()

    // Save this code
    function track(key) {
      let dep = depsMap.get(key) // Get the dep for this property
      if (!dep) {
        depsMap.set(key, (dep = new Set())) // No dep yet, so let's create one 
      }
      dep.add(effect) // Add this effect Since it's a set, it won't add the effect again if it already exists
    }

    // Run all the code I've saved 
    function trigger(key) {
      let dep = depsMap.get(key) // Get the dep for the key
      if (dep) {
        dep.forEach(effect => {
          effect() // If it exists, run each effect
        })
      }
    }

    let product = {
      price: 5,
      quantity: 2,
    }
    let total = 0

    let effect = () => {
      total = product.price * product.quantity
    }

    track('quantity')
    effect()
  </script>
</html>

当我们触发函数trigger('quantity')effect就运行了;控制台输出结果如下:

【Vue3响应式原理#01】Reactivity

现在我们就对 对象中的不同属性 有了一种跟踪依赖关系的方法

targetMap

What if we have multiple reactive objects that each need to track effects ?

如果我们有多个响应式对象,每个响应式对象属性都需要存储 effect 呢?例如?

let product = { price: 5, quantity: 2 } 
let user = { name: "burc", age: 18 }

到目前为止,我们有一张 depsMap,它存储了每个属性自己的依赖对象(属性到自己依赖对象的映射)。然后每个属性都拥有它们自己的并可以重新运行effectdep

我们这里需要一个其他对象,即 targetMap 。它的键以某种方式引用了我们的响应性对象,例如productuser

  • targetMap: 一个 WeakMap 对象,它储存了与每个 响应性对象属性 关联的依赖,在 Vue3 中,它被称为目标图
  • WeakMap: 与 Map 结构类似,但只接受对象作为键名(null除外),不接受其他类型的值作为键名

【Vue3响应式原理#01】Reactivity

用一个简单的例子告诉我们 WeakMap 是如何工作的,如想了解详细API请移步 阮一峰ES6文档-WeakMap

let product = { price: 5, quantity: 2 }

const targetMap = new WeakMap()
targetMap.set(product, "example code to test")

console.log(targetMap.get(product))
//"example code to test"

让我们来实现一下,代码如下:

<html>
  <head></head>
  <body>
    <div id="app">
      <div>targetMap</div>
    </div>
  </body>
  <script>
    const targetMap = new WeakMap() // For storing the dependencies for each reactive object

    // Save this code
    function track(target, key) {
      let depsMap = targetMap.get(target) // Get the current depsMap for this target(reactive object - product)
      if (!depsMap) {
        targetMap.set(target, (depsMap = new Map())) // If it doesn't exist, create it
      }
      let dep = depsMap.get(key) // Get the dependency object for this peoperty - quantity
      if (!dep) {
        depsMap.set(key, (dep = new Set())) // If it doesn't exist, create it
      }
      dep.add(effect) // Add the effect to the dependency
    }

    // Run all the code I've saved
    function trigger(target, key) {
      const depsMap = targetMap.get(target) // Does this object have any properties that have dependencies?
      if (!depsMap) {
        return // If no, return from the function immediately
      }
      let dep = depsMap.get(key) // Otherwise, check if this property has a dependency
      if (dep) {
        dep.forEach(effect => {
          effect()
        }) // Run those
      }
    }

    let product = { price: 5, quantity: 2 }
    let total = 0

    let effect = () => {
      total = product.price * product.quantity
    }

    track(product, 'quantity')
    effect()
  </script>
</html>

当我们触发函数 trigger(product, 'quantity')effect就运行了;控制台输出结果如下:

【Vue3响应式原理#01】Reactivity

diagram

让我们再分析概括一下图表

  • targetMap:存储了每个 响应性对象属性 关联的依赖;类型是 WeakMap
  • depsMap:存储了每个属性的依赖;类型是 Map
  • dep:存储了我们的effects,一个effects集,这些effect在值发生变化时重新运行;类型是 Set

【Vue3响应式原理#01】Reactivity

Now!我们就实现了一种储存不同effect的方法,但是我们还没有办法让我们的effect自动重新运行。这是第二个重要的部分,将在下一篇文章讲解!文章来源地址https://www.toymoban.com/news/detail-710874.html

到了这里,关于【Vue3响应式原理#01】Reactivity的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue3 数据响应式原理

    核心: 通过Proxy(代理): 拦截对data任意属性的任意(13种)操作, 包括属性值的读写, 属性的添加, 属性的删除等… 通过 Reflect(反射): 动态对被代理对象的相应属性进行特定的操作 Vue3的响应式比Vue2好在哪里? 效率更高了,Vue2中假设监听某个对象,该对象中有一万个属性,他要循

    2024年02月11日
    浏览(52)
  • Vue3响应式原理 私

    响应式的本质:当数据变化后会自动执行某个函数映射到组件,自动触发组件的重新渲染。 响应式的实现方式就是劫持数据,Vue3的reactive就是通过Proxy劫持数据,由于劫持的是整个对象,所以可以检测到任何对象的修改,弥补了2.0的不足。 名词解释: **副作用函数:**函数的

    2024年02月10日
    浏览(39)
  • 手写Vue3响应式数据原理

    我们想要对一个对象数据进行处理,从而实现更改dom。但如何更改对一个对象数据进行更改呢? vue2 的双向数据绑定是利⽤ES5 的⼀个 API ,Object.defineProperty()对数据进⾏劫持 结合 发布订阅模式的⽅式来实现的。 vue3 中使⽤了 ES6 的 ProxyAPI 对数据代理,通过 reactive() 函数给每⼀

    2024年02月11日
    浏览(48)
  • Vue3.0中的响应式原理

    实现原理: - 对象类型:通过 ``Object.defineProperty()``对属性的读取、修改进行拦截(数据劫持)。 - 数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。 存在问题: - 新增属性、删除属性, 界面不会更新。 - 直接通过下标修改数组, 界面

    2023年04月17日
    浏览(50)
  • Web前端 ---- 【Vue3】Proxy响应式原理

    目录 前言 安装Vue3项目 安装 Proxy 语法格式 从本文开始进入vue3的学习。本文介绍vue3中的响应式原理,相较于vue2中通过object.defineProperty(vue2中的响应式)来实现响应式,vue3中换成了Proxy来进行实现。 相较于vue2通过vue-cli脚手架来创建项目,这里更推荐使用create-vue来创建vue3的

    2024年01月16日
    浏览(69)
  • 【源码系列#05】Vue3响应式原理(Ref)

    ref: 接受一个参数值并返回一个响应式且可改变的 ref 对象。ref 对象拥有一个指向内部值的单一属性 .value 可以将 ref 看成 reactive 的一个变形版本,这是由于 reactive 内部采用 Proxy 来实现,而 Proxy 只接受对象作为入参,这才有了 ref 来解决值类型的数据响应, 如果传入 ref 的

    2024年02月03日
    浏览(35)
  • 【源码系列#02】Vue3响应式原理(Effect)

    专栏分享:vue2源码专栏,vue3源码专栏,vue router源码专栏,玩具项目专栏,硬核💪推荐🙌 欢迎各位ITer关注点赞收藏🌸🌸🌸 Vue3中响应数据核心是 reactive , reactive 的实现是由 proxy 加 effect 组合 ,上一章节我们利用 proxy 实现了一个简易版的 reactive,# 【源码系列#01】Vue3响应

    2024年02月05日
    浏览(42)
  • Vue2和Vue3响应式原理实现的核心

    Vue.js 是一个开源的渐进式 JavaScript 前端框架,主要用于构建用户界面和单页应用程序(SPA)。Vue.js 可以轻松地与其他库或现有项目集成使用,并被认为是开发响应式数据驱动的现代 Web 应用的一种有效方式。 Vue.js 的核心特点: 响应式数据绑定:Vue.js 可以通过对数据进行双

    2024年02月08日
    浏览(47)
  • 【Vue3响应式原理#02】Proxy and Reflect

    专栏分享:vue2源码专栏,vue3源码专栏,vue router源码专栏,玩具项目专栏,硬核💪推荐🙌 欢迎各位ITer关注点赞收藏🌸🌸🌸 以下是柏成根据Vue3官方课程整理的响应式书面文档 - 第二节,课程链接在此:Proxy and Reflect - Vue 3 Reactivity | Vue Mastery 本篇文章将解决 上一篇文章 结

    2024年02月05日
    浏览(62)
  • 【手撕源码】vue3响应式原理解析(文末抽奖)

    🐱 个人主页: 不叫猫先生 🙋‍♂️ 作者简介:2022年度博客之星前端领域TOP 2,前端领域优质作者、阿里云专家博主,专注于前端各领域技术,共同学习共同进步,一起加油呀! 💫优质专栏:vue3从入门到精通、TypeScript从入门到实践 📢 资料领取:前端进阶资料以及文中源

    2024年02月03日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包