美文网首页
Vue 3 响应式原理四 - Computed Values &

Vue 3 响应式原理四 - Computed Values &

作者: AizawaSayo | 来源:发表于2021-08-26 08:54 被阅读0次

    你可能会想说“为什么我们不直接使用计算属性来处理这些副作用?”
    这是我们的例子:

    let product = reactive({ price: 5, quantity: 2 })
    let salePrice = ref(0)
    let total = 0
    effect(() => {
      salePrice.value = product.price * 0.9
    })
    effect(() => {
      total = salePrice.value * product.quantity
    })
    

    我们来转换一下:

    let product = reactive({ price: 5, quantity: 2 })
    let salePrice = computed(() => {
      return product.price * 0.9
    })
    let total = computed(() => {
      return salePrice.value * product.quantity
    })
    

    请注意salePrice计算属性如何包含在total计算属性中,我们需要使用.value访问它。看起来我们正在创建另一个ref响应式引用。
    下面是如何定义我们的computed函数

    function computed(getter) {
      let result = ref()  // 创建一个新的响应式引用
      effect(() => (result.value = getter())) // 将 result 的值设置为 getter 的返回值
      return result // 返回这个 ref
    }
    

    这就是全部了。你可以在 Github 上找到完整代码 computed.js.

    规避了 Vue 2 中更改检测警告的漏洞

    值得一提的是,我们可以用响应式对象做一些 Vue 2 无法做到的事情。比如我们可以像这样添加新的响应式式属性:

    let product = reactive({ price: 5, quantity: 2 })
    ...
    product.name = 'Shoes'
    effect(() => {
      console.log(`Product name is now ${product.name}`)
    })
    product.name = 'Socks'
    

    就如你期望的那样,控制台打印出:

    Product name is now Shoes
    Product name is now Socks

    这在 Vue 2 中是不可能的,因为 Vue 2 的响应性是用 Object.definePropertygettersetter添加到单个对象属性来实现的。现在有了 Proxy,我们可以毫无顾虑地添加新属性,并且它们可以立即响应。

    我们的代码 VS Vue 3 源码

    您可能想知道,我们的代码是否能大致与 Vue 3 源码等效?
    可以像下图那样操作:

    • git clone vue-next
    • yarn install
      -yarn build reactivity
    • 将在packages/reactivity/dist/找到的reactivity.cjs.js引入到我们的示例文件顶部,代替我们自己写的reactivecomputedeffect方法。

    vue-3-reactivity

    var { reactive, computed, effect } = require('./reactivity.cjs')
    // 后面的代码都一样,故省略
    

    打印的结果依然是一样:

    Before updated quantity total (should be 9) = 9 salePrice (should be 4.5) = 4.5
    After updated quantity total (should be 13.5) = 13.5 salePrice (should be 4.5) = 4.5
    After updated price total (should be 27) = 27 salePrice (should be 9) = 9
    Product name is now Shoes
    Product name is now Socks

    嗯,所以我们的响应式系统是不是和 Vue 的差不多了 ?但真实情况 Vue 的版本肯定要复杂得多。 让我们来看看构成 Vue 3 的响应式系统的文件吧。

    Vue 3 响应式源码文件

    我们在 Vue 3 源码包/packages/reactivity/src/可以找到以下文件。它们是TypeScript (ts)文件,但你应该能够读懂它们(即使不熟悉TS)。

    • effect.ts - 定义了effect函数(用来封装可能包含响应式引用和对象的代码)。还包含了 get 属性时调用的track和 set 属性调用的trigger
    • baseHandlers.ts - 包含 Proxy handlers,譬如getset, 它们分别调用了tracktrigger(来自effect.ts)。
    • reactive.ts - 定义了响应式语法的功能,它创建了一个 ES6 Proxy,并使用getset(来自basehandlers.ts)作为 proxy 的处理程序(handlers)。
    • ref.ts - 通过对象访问器定义创建响应式引用的方法。还包含toRefs,它将响应式对象转换为访问原始 proxy 的一个个响应式引用。
    • computed.ts - 定义了计算属性,使用effect和对象访问器并且返回了一个类似Ref的对象。(和我们的实现稍微有点不同)。

    这些文件包含了 Vue 响应式系统的核心功能。

    Vue 3 响应式原理一 - Vue 3 Reactivity
    Vue 3 响应式原理二 - Proxy and Reflect
    Vue 3 响应式原理三 - activeEffect & ref
    Vue 3 响应式原理四 - Computed Values & Vue 3 源码

    相关文章

      网友评论

          本文标题:Vue 3 响应式原理四 - Computed Values &

          本文链接:https://www.haomeiwen.com/subject/lcfjiltx.html