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