一. reactive()
在 Vue3 中,可以使用 reactive() 创建一个响应式对象或数组:
xml
<script setup>
import { reactive } from 'vue'
const state = reactive({ count: 0 })
</script>
<template>
<button @click="state.count++">
{{ state.count }}
</button>
</template>
需要注意的是,reactive() 返回的是一个原始对象的 Proxy,它与原始对象是不相等的。只有代理对象是响应式的,更新原始对象并不会触发更新。
js
const row = {}
const proxy = reactive(raw)
console.log( proxy === row) // false
reactive() 的局限性:
- 有限的值类型:reactive() 只能用于对象、数组等对象类型,而不能用于基础数据类型(string、number、boolean)
- 不能替换整个对象,会导致对初始引用的响应性连接丢失
xml
<script setup>
import { reactive } from 'vue'
let state = reactive({ count: 0 })
const increase = () => {
state = { count: 1 } // state.count = 1 才能正确修改
}
</script>
<template>
<button @click="increase">
{{ state.count }} <!-- 点击button,始终显示为0 -->
</button>
</template>
- 对解构操作不友好:将响应式对象的原始类型属性解构为本地变量时,或者将该属性传递给函数时,会丢失响应性。
xml
<script setup>
import { reactive } from 'vue'
let state = reactive({ count: 0 })
let { count } = state
const increase = () => {
count++
}
</script>
<template>
<button @click="increase">
{{ state.count }} <!-- 点击button,始终显示为0 -->
</button>
</template>
二. ref()
ref() 将传入的参数包装成一个带有 value 属性的 ref 对象。在模板中使用 ref 时,不需要附加 .value。
xml
<script setup>
import { ref } from 'vue'
const count = ref(0)
console.log(count) // {value: 0},使用 count.value++
</script>
<template>
<button @click="count++">
{{ count }} <!-- 无需.value -->
</button>
</template>
ref() 的参数一般时基础数据类型,也可以是对象类型。如果参数是对象类型,系统会自动将 ref 转成 reactive。
xml
<script setup>
import { ref } from 'vue'
const state = ref({ count: 0 })
console.log(state.value) // Proxy(object) {count: 0}
const increase = () => {
state.value.count++
}
</script>
<template>
<button @click="increase"> <!-- state.count++ -->
{{ state.count }} <!-- 无需.value -->
</button>
</template>
一个包含对象的 ref 可以响应式地替换整个对象:
xml
<script setup>
import { ref } from 'vue'
const state = ref({ count: 0 })
const increase = () => {
state.value = { count: 1 }
}
</script>
<template>
<button @click="increase">
{{ state.count }} <!-- 点击button后由0变为1 -->
</button>
</template>