• 0

  • 483

Vue3 文档阅读 —— reactivity 响应式基础

智能的司机

我是老司机

1星期前

Vue 官方团队于 2020 年 9 月 18 日晚 11 点半左右发布了 Vue3.0 版本 🎉。代号为 One Piece。

Vue 3.0 终于发布了,具体更新内容详见 v3.0.0。官网地址 Vue,但内容还都是英文的,毕竟刚发布嘛,中文内容还没那么快。

Vue3 英文指引

索性不如自己阅读仓库文档,看看 Vue3 都给我们带来了哪些具体变化。

原文地址:github.com/vuejs/docs-…

响应式基础

声明响应式状态

要从 JavaScript 对象创建一个响应式状态,可以使用 reactive 方法:

import { reactive } from 'vue'

// 响应式状态
const state = reactive({
  count: 0
})
复制代码

reactive 相当于 Vue 2.x 中的 Vue.observable() API ,为避免与 RxJS 中的 observables 混淆因此对其重命名。这里返回的状态是一个响应式对象。该响应式转换是“深度转换”——它会影响传入对象的所有属性值。

Vue 中响应式状态的基本场景是我们可以在渲染期间使用它。借助独立的依赖跟踪体系,当响应式状态改变时视图会自动更新。

这就是 Vue 响应式系统的本质。当从组件中的 data() 返回一个对象时,它在内部通过 reactive() 变成响应式对象。模板会被编译成能够使用这些响应式 property 的渲染函数

响应式基础 API 章节你可以学习更多关于 reactive 的内容。

创建独立的响应值作为 refs

想象一下,我们有一个独立的原始值 (例如,一个字符串),我们想让它变成响应式的。当然,我们可以把这个字符串作为唯一的属性创建对象,并将其传递给 reactive。不过 Vue 为我们提供了一个可以实现相同效果的方法 ——ref

import { ref } from 'vue'

const count = ref(0)
复制代码

ref 将返回一个响应式可变的对象,作为它所持有的内部值的响应式引用--这就是名称的由来。此对象只包含一个名为 value 的属性 :

import { ref } from 'vue'

const count = ref(0)
console.log(count.value) // 0

count.value++
console.log(count.value) // 1
复制代码

Ref 展开

当一个 ref 在渲染上下文(从 setup () 中返回的对象)上作为一个属性返回,并在模板中被访问时,它会自动展开其内部值。故在模板中就不必追加 .value了:

<template>
  <div>
    <span>{{ count }}</span>
    <button @click="count ++">Increment count</button>
  </div>
</template>

<script>
  import { ref } from 'vue'
  export default {
    setup() {
      const count = ref(0)
      return {
        count
      }
    }
  }
</script>
复制代码

访问响应式对象

ref 作为响应式对象的属性被访问或变更时,它会自动展开内部值,表现行为类似于普通的属性

const count = ref(0)
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
console.log(count.value) // 1
复制代码

Ref 展开仅发生在被响应式 Object 内嵌的时候。当从 Array 或原生集合类型如 Map访问 ref 时,不会进行展开:

const books = reactive([ref('Vue 3 Guide')])
// 需要使用 .value
console.log(books[0].value)

const map = reactive(new Map([['count', ref(0)]]))
// 需要使用 .value
console.log(map.get('count').value)
复制代码

解构响应式状态

当我们要使用大型响应式对象的一些属性时,可能会考虑使用 ES6 解构来获取我们想要的属性值:

import { reactive } from 'vue'

const book = reactive({
  author: 'Vue Team',
  year: '2020',
  title: 'Vue 3 Guide',
  description: 'You are reading this book right now ;)',
  price: 'free'
})

let { author, title } = book
复制代码

遗憾的是,使用解构的两个属性响应式都会丢失。对于这种情况,我们需要将我们的响应式对象转换为一组 ref。这些 ref 将保留与源对象的响应式关联:

import { reactive, toRefs } from 'vue'

const book = reactive({
  author: 'Vue Team',
  year: '2020',
  title: 'Vue 3 Guide',
  description: 'You are reading this book right now ;)',
  price: 'free'
})

let { author, title } = toRefs(book)

title.value = 'Vue 3 Detailed Guide' // 我们需要使用 .value 作为标题,现在是 ref
console.log(book.title) // 'Vue 3 Detailed Guide'
复制代码

你可以在 Refs API 部分中了解更多有关 `refs' 的信息

使用 readonly 防止篡改响应式对象

有时我们想跟踪响应式对象 (refreactive) 的变化,但我们也希望在应用程序的特定位置上防止对它的修改。例如,当我们有一个被 provide 的响应式对象时,我们不想让它在注入的时候被改变。为此,我们可以给原始对象创建一个只读的 Proxy 对象:

import { reactive, readonly } from 'vue'

const original = reactive({ count: 0 })

const copy = readonly(original)

// 变更 original 会触发依赖于 copy 的监听器(译者注:即 copy 也能得到变更后的值)

original.count++

// 变更 copy 会失败并弹出警告信息
copy.count++ // 警告: "Set operation on key 'count' failed: target is readonly."
复制代码
免责声明:文章版权归原作者所有,其内容与观点不代表Unitimes立场,亦不构成任何投资意见或建议。

483

相关文章推荐

未登录头像

暂无评论