Vue3官方文档翻译之Reactivity Fundamentals


引言

突然不知道这章写了啥, 感觉内容有点干, 顾着翻译去了, 没有吸收消化. 还是总结下, 主要是就是响应式的对象如何和template结合的, 响应式对象是通过JavaScript的代理对象实现的; 响应式的对象有分为深响应和浅响应; 完成响应式的对象在作为函数参数或者解构的时候会有局限性,因此提出了ref()来避免此问题,并讲接了ref的拆箱问题.

原文地址: http://blog.duhbb.com/2022/02/11/translation-of-reactivity-fundamentals-in-vue-3-offiicial-doc/

欢迎访问我的博客: http://blog.duhbb.com/

Reactivity Fundamentals: 我也不知道怎么翻译, 就当作是响应式原理或者基础吧.

P.S. 我看的这个版本是 Composition API, 所以如果有偏差的话, 应该是API风格上的不同, 请自行甄别.

声明响应式的状态

我们可以使用 reactive() 函数创建一个响应式的对象或者数组.

妙啊, 创建之后呢?

import { reactive } from 'vue'

const state = reactive({ count: 0 })

响应时的对象都是JavaScript代理对象, 学过代理模式的应该都懂吧, 不会有人觉得用common 对象就能响应式吧, 我瞎逼逼的.

但是这些代理对象看上去和普通对象并没有什么区别. 不同的是Vue可以跟踪代理对象的属性访问以及响应式对象的变更. 如果你好奇这个在Vue中的实现原理, 那么我推荐你了解一下Reactivity in Depth, 不要猴急, 你先把这篇看完了, 再去深入了解.

也可以参考: Typing Reactive

为了在组件模板中使用响应式的对象, 声明并且从组件的setup()函数中返回这个对象.

P.S. Options API 应该是从data()返回的吧.

import { reactive } from 'vue'

export default {
  // `setup`是一个特殊的钩子, 专门用于composition API.
  setup() {
    const state = reactive({ count: 0 })

    // 将响应式状态暴露给模板
    return {
      state
    }
  }
}

这样, state就和template关联起来了, 你瞧瞧多么牛逼的框架......

{{ state.count }}

类似的, 我们可以在同一个域中声明函数来操作响应式的状态, 并将将她作为方法和state一起暴露.

import { reactive } from 'vue'

export default {
  setup() {
    const state = reactive({ count: 0 })

    // 擦, mutation的函数是放在scope中的?
    function increment() {
      state.count++
    }

    // don't forget to expose the function as well.
    return {
      state,
      increment
    }
  }
}

被暴露的方法一般都是作为事件响应的监听器:


小心: 自动地拆箱仅适用于顶层属性, 对于refs的嵌套访问则不会被拆箱:

const object = { foo: ref(1) }

{{ object.foo }} 

正如设想的那样, foo 并不会被拆箱, 呵呵, 我还没有验证.

响应式对象中的ref的拆箱

当一个ref作为一个响应式的对象的属性进行访问或者修改的时候, 她会被自动的进行拆箱, 就像正常的属性那样:

const count = ref(0)

/* state已经是一个响应式的对象, 她有一个ref形式的属性, 这个会被自动拆箱, 不需要是top-level了 */
/* 感觉我已经理解了这个, 但是没有实践 */
const state = reactive({
  count
})

console.log(state.count) // 0

state.count = 1
console.log(count.value) // 1

如果一个新的ref替换了原来的ref, 她将会替代原来的ref:

const otherCount = ref(2)

state.count = otherCount
console.log(state.count) // 2
// original ref is now disconnected from state.count
console.log(count.value) // 1

ref的拆箱只会发生在作为深层的响应式对象的时候, 而作为浅层响应对象的属性时, 则不会被拆箱.

数组和集合中的ref的拆箱

和响应式对象不一样, 当ref作为响应式数组或者集合类型的元素被访问的时候并不会发生拆箱(这是为什么呢?):

const books = reactive([ref('Vue 3 Guide')])
// need .value here
console.log(books[0].value)

const map = reactive(new Map([['count', ref(0)]]))
// need .value here
console.log(map.get('count').value)

响应式的传递性(实验特性)

必须将 .value 和 refs 进行配合使用时JavaScript这个语言所施加的限制. 然而, 通过运行期的转换在合适的位置追加 .value 则可以提高 ergonomics. Vue提供了编译期的转换使我们可以将之前的 "counter" 例子写成这样:




关于Reactivity Transform可以在她的专题了解, 提醒各位这个目前还只是实验性滴.

结束语

突然不知道这章写了啥, 感觉内容有点干, 顾着翻译去了, 没有吸收消化. 还是总结下, 主要是就是响应式的对象如何和template结合的, 响应式对象是通过JavaScript的代理对象实现的; 响应式的对象有分为深响应和浅响应; 完成响应式的对象在作为函数参数或者解构的时候会有局限性,因此提出了ref()来避免此问题,并讲接了ref的拆箱问题.

原文地址: http://blog.duhbb.com/2022/02/11/translation-of-reactivity-fundamentals-in-vue-3-offiicial-doc/

欢迎访问我的博客: http://blog.duhbb.com/