响应性基础

声明响应式状态

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

import { reactive } from 'vue'

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

reactive 返回一个响应式的对象状态,该响应式转换是“深度转换”,它会影响传递对象的所有嵌套 property。

当从组件中 data() 返回一个对象时,该对象会交由 reactive() 使其成为响应式对象,模板会被编译成能够使用这些响应式 property 的渲染函数


创建独立的响应式值作为 refs

ref 返回一个可变的响应式对象,该对象作为一个响应式的引用维护着其内部的值,这就是 ref 名称的来源,该对象只包含一个名为 value 的 property:

import { ref } from 'vue'

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

count.value++
console.log(count.value) // 1


Ref 解包

当 ref 作为渲染上下文 (从 setup() 中返回的对象) 上的 property 返回并可以在模板中被访问时,它将自动浅层次解包内部值。只有访问嵌套的 ref 时需要在模板中添加 .value

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

<script>
  import { ref } from 'vue'
  export default {
    setup() {
      const count = ref(0)
      return {
        count,

        nested: {  // 嵌套的 ref 
          count
        }
      }
    }
  }
</script>


访问响应式对象

当 ref 作为响应式对象的 property 被访问或更改时,为使其行为类似于普通 property,它会自动解包内部值:

const count = ref(0)
const state = reactive({
  count
})

// 虽然此处的 count 是一个 ref 响应式对象,但在访问时仍能直接访问到其value,因为reactive自动对其进行了解包;
console.log(state.count) // 0 

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

如果将新的 ref 赋值给现有 ref 的 property,将会替换旧的 ref:

const otherCount = ref(2)

state.count = otherCount  // 此处会直接替换旧的 ref 对象,而不是修改 ref 对象的value
console.log(state.count) // 2
console.log(count.value) // 1


Ref 解包仅发生在被响应式对象嵌套时,当从 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)


响应式状态解构

当使用解构来获取响应式对象的一些 property 时,被获取的属性响应性将丢失;

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) // toRefs将响应式对象转为普通对象,并将对象中每个属性都是指向原始对象相应属性的ref对象;

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


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

如果想跟踪响应式对象 (ref 或 reactive) 的变化,但也想防止在应用程序的某个位置更改它;例如,当有一个被 provide 的响应式对象时,不想让它在注入之后被改变。为此,可以基于原始对象创建一个只读的 proxy 对象:

import { reactive, readonly } from 'vue'

const original = reactive({ count: 0 })

const copy = readonly(original)

// 通过 original 修改 count,将会触发依赖 copy 的侦听器

original.count++

// 通过 copy 修改 count,将导致失败并出现警告
copy.count++ // 警告: "Set operation on key 'count' failed: target is readonly."


举报

© 著作权归作者所有


0