在Vue3中露久,提供reactive和ref響應(yīng)式數(shù)據(jù)的API胧后。reactive()方法運用proxy的代理對象,解決大量在Vue2中Object.defineProperty的痛點抱环,更好支持對象監(jiān)聽壳快,但proxy并不能直接監(jiān)聽基礎(chǔ)類型,需要每次構(gòu)建一個對象镇草,在用proxy代理對象就會造成極大性能損耗眶痰,因此Vue3就提供ref方法,通過返回一個簡單的響應(yīng)式對象梯啤,專門處理基礎(chǔ)類型的數(shù)據(jù)響應(yīng)竖伯。
-
ref
ref函數(shù)常用于基礎(chǔ)類型。
- ref接收參數(shù)因宇,并將其包裹在一個帶有 .value 屬性的 ref 對象中返回七婴。
ref函數(shù)接受的是一個基本類型的單值,需要將其轉(zhuǎn)換成對象可以通過value來訪問察滑,可以使用class類打厘,get語法將對象屬性綁定到查詢該屬性時將被調(diào)用的函數(shù) 。
const count = ref(0)
console.log(count) // { value: 0 }
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
- 在組件模板中訪問 ref贺辰,請從組件的 setup() 函數(shù)中聲明并返回它們户盯。
<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
</script>
<div>{{ count }}</div>
-
reactive
reactive()
常用來定義對象(或者數(shù)組)類型數(shù)據(jù),返回的是一個原始對象的Proxy饲化。與將內(nèi)部值包裝在特殊對象中的 ref 不同莽鸭,reactive() 將使對象本身具有響應(yīng)性。
import { reactive } from 'vue'
const state = reactive({ count: 0 })
在模板中使用:
<button @click="state.count++">
{{ state.count }}
</button>
reactive()
API 有一些局限性:
有限的值類型:它只能用于對象類型 (對象吃靠、數(shù)組和如
Map
硫眨、Set
這樣的集合類型)。它不能持有如string
巢块、number
或boolean
這樣的原始類型礁阁。不能替換整個對象:由于 Vue 的響應(yīng)式跟蹤是通過屬性訪問實現(xiàn)的,因此我們必須始終保持對響應(yīng)式對象的相同引用夕冲。這意味著我們不能輕易地“替換”響應(yīng)式對象氮兵,因為這樣的話與第一個引用的響應(yīng)性連接將丟失:
let state = reactive({ count: 0 })
// 上面的 ({ count: 0 }) 引用將不再被追蹤
// (響應(yīng)性連接已丟失!)
state = reactive({ count: 1 })
- 對解構(gòu)操作不友好:當我們將響應(yīng)式對象的原始類型屬性解構(gòu)為本地變量時歹鱼,或者將該屬性傳遞給函數(shù)時泣栈,我們將丟失響應(yīng)性連接:
const state = reactive({ count: 0 })
// 當解構(gòu)時,count 已經(jīng)與 state.count 斷開連接
let { count } = state
// 不會影響原始的 state
count++
// 該函數(shù)接收到的是一個普通的數(shù)字
// 并且無法追蹤 state.count 的變化
// 我們必須傳入整個對象以保持響應(yīng)性
callSomeFunction(state.count)
總結(jié)
ref
的局限在于每次訪問基礎(chǔ)類型值時都需要通過.value,但在處理簡單數(shù)據(jù)時更為直觀和高效南片。
reactive
雖能直接操作對象屬性掺涛,但對于基礎(chǔ)類型則無能為力,且存在不能直接替換整個響應(yīng)式對象疼进、解構(gòu)操作可能失去響應(yīng)性等問題薪缆。