Vue3中關(guān)于ref和reactive的區(qū)別分析
一、reactive
數(shù)據(jù)類型
reactive()可用于創(chuàng)造一個(gè)響應(yīng)式對(duì)象,它接受一個(gè)參數(shù),這個(gè)參數(shù)的類型是一個(gè)重點(diǎn),接下來我們先看看Vue3的源碼里是怎么處理的。
function createReactiveObject(
target: Target,
isReadonly: boolean,
baseHandlers: ProxyHandler<any>,
collectionHandlers: ProxyHandler<any>,
proxyMap: WeakMap<Target, any>
) {
if (!isObject(target)) {
if (__DEV__) {
console.warn(`value cannot be made reactive: ${String(target)}`)
}
return target
}
// ...
}Vue3主要是調(diào)用createReactiveObject函數(shù)來創(chuàng)建reactive對(duì)象,從源碼里可以看到,該函數(shù)會(huì)首先判斷reactive()傳入的參數(shù)是不是一個(gè)對(duì)象,如果不是則不做任何處理,直接返回原值,同時(shí)開發(fā)環(huán)境下會(huì)在控制臺(tái)輸出一句警告。所以嚴(yán)格上來說,reactive()并不是像有些人說的不能傳入基本類型的參數(shù),它可以傳,只是這種數(shù)據(jù)會(huì)失去響應(yīng)式。
let name = reactive('張三')
setTimeout(() => {
name = '李四'
console.log(name, 'name') // 李四
}, 3000)
<template>
<h1>{{ name }}</h1>
</template>上面模板里仍然顯示的是張三,因?yàn)閚ame沒有響應(yīng)式不會(huì)觸發(fā)視圖更新。
原始數(shù)據(jù)與響應(yīng)式數(shù)據(jù)
我們可以先定義一個(gè)原始對(duì)象,再將對(duì)象傳入reactive(),此時(shí)原始對(duì)象和響應(yīng)式對(duì)象會(huì)互相干擾。
let data = { name: '張三' } // 原始對(duì)象
let state = reactive(data)
setTimeout(() => {
state.name = '李四'
console.log(data.name) // 李四
}, 2000)修改響應(yīng)式對(duì)象state.name的值,原始對(duì)象data.name也會(huì)同步變化。
反過來也是一樣,修改data.name,state.name也會(huì)同步變化,但需要注意的是:這種情況下雖然state.name發(fā)生了改變但視圖并不會(huì)更新。
let data = { name: '張三' }
let state = reactive(data)
setTimeout(() => {
data.name = '李四'
console.log(state.name) // 李四,但template里仍為張三
}, 2000)
</script>
<template>
<h1>{{ state.name }}</h1>
</template>所以如果你是通過定義一個(gè)對(duì)象再將對(duì)象傳入reactive的話,建議始終是對(duì)響應(yīng)式對(duì)象進(jìn)行操作而不是原始數(shù)據(jù)。
二、ref
數(shù)據(jù)類型
export function ref(value?: unknown) {
return createRef(value, false)
}從源碼里可以知道,ref()接受一個(gè)參數(shù),參數(shù)可以是任意類型,這也是ref與reactive的區(qū)別之一,不管是基本類型還是引用類型ref都具備響應(yīng)式,另外ref要通過.value進(jìn)行取值。
let name = ref('張三') // 可以是基本類型
// 也可以是引用類型
let user = ref({
name: '張三',
age: 18
})
console.log(name.value)
console.log(user.value)原始數(shù)據(jù)與響應(yīng)式數(shù)據(jù)
ref與reactive一樣,修改原始數(shù)據(jù)或響應(yīng)式數(shù)據(jù)都會(huì)同步改變對(duì)方的值,且在修改原始對(duì)象時(shí)都無法觸發(fā)視圖更新。
ref也可能是一種reactive
function createRef(rawValue: unknown, shallow: boolean) {
if (isRef(rawValue)) {
return rawValue
}
return new RefImpl(rawValue, shallow)
}
class RefImpl<T> {
private _value: T
private _rawValue: T
public dep?: Dep = undefined
public readonly __v_isRef = true
constructor(value: T, public readonly __v_isShallow: boolean) {
this._rawValue = __v_isShallow ? value : toRaw(value)
this._value = __v_isShallow ? value : toReactive(value)
}
get value() {
trackRefValue(this)
return this._value
}
set value(newVal) {
const useDirectValue =
this.__v_isShallow || isShallow(newVal) || isReadonly(newVal)
newVal = useDirectValue ? newVal : toRaw(newVal)
if (hasChanged(newVal, this._rawValue)) {
this._rawValue = newVal
this._value = useDirectValue ? newVal : toReactive(newVal)
triggerRefValue(this, newVal)
}
}
}通過源碼可以知道,ref是通過RefImpl這個(gè)類來創(chuàng)建的,而在RefImpl內(nèi)部會(huì)調(diào)用toReactive函數(shù),如果不是基本類型的數(shù)據(jù),會(huì)將其轉(zhuǎn)換成reactive。
可重新賦值對(duì)象
使用reactive時(shí),對(duì)響應(yīng)式對(duì)象重新賦值是會(huì)失去響應(yīng)式的。
let state = reactive({ name: '張三' })
setTimeout(() => {
state = { name: '李四'}
console.log(state.name) // 李四,數(shù)據(jù)變更了但視圖不會(huì)更新
}, 2000)ref則沒有這種問題。
let state = ref({ name: '張三' })
setTimeout(() => {
state.value = { name: '李四'}
console.log(state.value.name) // 數(shù)據(jù)變更,同時(shí)視圖也會(huì)更新
}, 2000)使用watch監(jiān)聽ref對(duì)象需要deep
let state = ref({ name: '張三' })
setTimeout(() => {
state.value.name = '李四'
}, 2000)
watch(state, () => {
console.log(state.value.name)
}, { deep: true })reactive不加deep: truewatch也會(huì)觸發(fā),而ref則需要手動(dòng)加上。
小結(jié)
- 對(duì)于響應(yīng)式而言,ref支持對(duì)象類型和基本類型,而reactive只支持對(duì)象類型
- 當(dāng)ref是對(duì)象類型的時(shí)候,本質(zhì)上也是一個(gè)reactive
- 對(duì)象類型的ref和reactive,其響應(yīng)式底層原理都是Proxy
以上就是Vue3中關(guān)于ref和reactive的區(qū)別分析的詳細(xì)內(nèi)容,更多關(guān)于vue3 ref 和reactive的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Vue3.0中Ref與Reactive的區(qū)別示例詳析
- vue3?中ref和reactive的區(qū)別講解
- 前端vue3中的ref與reactive用法及區(qū)別總結(jié)
- Vue3 的ref和reactive的用法和區(qū)別示例解析
- Vue3中ref和reactive的基本使用及區(qū)別詳析
- Vue3中ref和reactive的區(qū)別及說明
- vue3.0中ref與reactive的區(qū)別及使用場(chǎng)景分析
- vue3中reactive和ref的實(shí)現(xiàn)與區(qū)別詳解
- vue3 ref 和reactive的區(qū)別詳解
- vue3中ref和reactive的區(qū)別舉例詳解
相關(guān)文章
element-ui復(fù)雜table表格動(dòng)態(tài)新增列、動(dòng)態(tài)調(diào)整行以及列順序詳解
這篇文章主要給大家介紹了關(guān)于element-ui復(fù)雜table表格動(dòng)態(tài)新增列、動(dòng)態(tài)調(diào)整行以及列順序的相關(guān)資料,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2023-08-08
淺析Proxy可以優(yōu)化vue的數(shù)據(jù)監(jiān)聽機(jī)制問題及實(shí)現(xiàn)思路
這篇文章主要介紹了淺析Proxy可以優(yōu)化vue的數(shù)據(jù)監(jiān)聽機(jī)制問題及實(shí)現(xiàn)思路,需要的朋友可以參考下2018-11-11
vue2.0結(jié)合DataTable插件實(shí)現(xiàn)表格動(dòng)態(tài)刷新的方法詳解
這篇文章主要介紹了vue2.0結(jié)合DataTable插件實(shí)現(xiàn)表格動(dòng)態(tài)刷新的方法,結(jié)合具體項(xiàng)目實(shí)例形式分析了vue2.0結(jié)合DataTable插件實(shí)現(xiàn)表格動(dòng)態(tài)刷新過程中遇到的問題與相應(yīng)的解決方法,需要的朋友可以參考下2017-03-03
windows下vue-cli導(dǎo)入bootstrap樣式
這篇文章主要介紹了windows下vue-cli導(dǎo)入bootstrap樣式,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-04-04
vue proxy 的優(yōu)勢(shì)與使用場(chǎng)景實(shí)現(xiàn)
這篇文章主要介紹了vue proxy 的優(yōu)勢(shì)與使用場(chǎng)景實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
vue axios數(shù)據(jù)請(qǐng)求及vue中使用axios的方法
axios 是一個(gè)基于Promise 用于瀏覽器和 nodejs 的 HTTP 客戶端,在vue中數(shù)據(jù)請(qǐng)求需要先安裝axios。這篇文章主要介紹了vue axios數(shù)據(jù)請(qǐng)求及vue中使用axios的方法,需要的朋友可以參考下2018-09-09
Vue執(zhí)行方法,方法獲取data值,設(shè)置data值,方法傳值操作
這篇文章主要介紹了Vue執(zhí)行方法,方法獲取data值,設(shè)置data值,方法傳值操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-08-08
vue中選項(xiàng)卡點(diǎn)擊切換且能滑動(dòng)切換功能的實(shí)現(xiàn)代碼
本文通過實(shí)例代碼給大家介紹了vue中選項(xiàng)卡點(diǎn)擊切換且能滑動(dòng)切換功能,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下2018-11-11
在vue項(xiàng)目中 實(shí)現(xiàn)定義全局變量 全局函數(shù)操作
這篇文章主要介紹了在vue項(xiàng)目中 實(shí)現(xiàn)定義全局變量 全局函數(shù)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-10-10

