声明响应式状态
有两种 ref()
与 reactive()
ref()
ref()
是将普通的 js
数值包装进一个特殊对象中, 对数值的操作需要通过 .value
来进行, 可以用来包装任何类型的值,包括深层嵌套的对象、数组或者 JavaScript 内置的数据结构
内部如何实现响应式操作的?
通过get
,set
操作实现,vue
追踪了每个调用了get
操作的组件, 然后在set
被操作时, 触发这些 “追踪对象” 的修改
<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
</script>
<template>
<button @click="increment">
{{ count }}
</button>
</template>
reactive()
reactive()
是将对象包装成一个代理对象, 使用上不需要 .value
, 直接正常使用, 一般用来包装复杂类型
内部实现方式
通过Javascripte 代理
, 代理了包装对象的所有数据的访问与修改, Vue 通过拦截这些操作进行依赖追踪和触发更新
reactive()
存在局限性, 推荐使用ref()
- 只能包装对象类型 (对象、数组和如
Map
、Set
这样的集合类型)。它不能持有如string
、number
或boolean
这样的原始类型- 只能通过代理对象进行操作, 不然就会失去响应性, 不支持替换与解构
<script setup>
import { reactive } from 'vue'
const state = ref({
count: 0
})
function increment() {
state.count++
}
</script>
<template>
<button @click="increment">
{{ state.count }}
</button>
</template>
嵌套与解包注意事项
ref()
嵌套进reactive()
可以自动解构
const msg = ref('Hello World!') const count = ref(0) const state = reactive({ count, msg }) function increment() { state.count++ state.msg += "ttt" }
- 作为数组或原生集合类型时, 无法自动解构, 需要用
.value
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)