Vue3中的ref和reactive函數(shù)如何使用?區(qū)別是什么?

ref函數(shù)

語(yǔ)法:

復(fù)制const xxx=ref(initValue)

接受的數(shù)據(jù)類型:基本類型,對(duì)象類型

作用:

把參數(shù)加工成一個(gè)響應(yīng)式對(duì)象,全稱為reference對(duì)象(我們下面一律簡(jiǎn)稱為ref對(duì)象)

核心原理:

響應(yīng)式依賴Object.defineProperty()的get()和set()。

Ref函數(shù)對(duì)于基本數(shù)據(jù)類型的參數(shù)

基本使用:

復(fù)制?

{{Str}}

import {ref} from 'vue'export default {? setup(){? ? const Str =ref('hello')? ? return{? ? ? Str? ? }? }}

上面我們定義了一個(gè)Str變量來(lái)接收ref加工生成的ref對(duì)象,我們都知道對(duì)象的數(shù)據(jù)都是以鍵值對(duì)的形式存儲(chǔ)的,但是在這里為什么直接把Str給return出去, 并且模板里可以直接寫(xiě)Str這個(gè)對(duì)象呢,我們的源數(shù)據(jù)呢?帶著這個(gè)疑問(wèn)我們來(lái)輸出一下Str:

復(fù)制setup(){? ? const Str =ref('hello')? ? console.log(Str)? ? return{? ? ? Str? ? }}

打印結(jié)果如下:

復(fù)制RefImpl__v_isRef: true_rawValue: "hello"_shallow: false_value: "hello"value: "hello"[[Prototype]]: Object

在這里我們看到了ref對(duì)象身上的一個(gè)屬性?value,沒(méi)錯(cuò),我們存入的值就對(duì)應(yīng)在value屬性上,至于為什么直接return出是Str而不是Str.value。是因?yàn)閂ue幫了我們一個(gè)忙,我們?cè)谶@里可以簡(jiǎn)寫(xiě),return出去的Str就相當(dāng)于Str.value,當(dāng)然,非要寫(xiě).value的形式也不是不可以。不過(guò)這里需要注意的是,在setup函數(shù)中操作Str中的數(shù)據(jù)不可以簡(jiǎn)寫(xiě)。

響應(yīng)式原理:

對(duì)于基本數(shù)據(jù)類型說(shuō)完了它的基本用法,下面我們來(lái)說(shuō)說(shuō)他的響應(yīng)式原理,也就是我們?yōu)槭裁捶且靡粋€(gè)ref對(duì)象來(lái)接受數(shù)據(jù),而不是直接就定義好一個(gè)字符串'hello',然后去直接操作這個(gè)字符串?

對(duì)于ref函數(shù),數(shù)據(jù)參數(shù)和它加工生成的ref對(duì)象二者存在著某種“契約”,我們把加工好的參數(shù)也就是ref對(duì)象交出去之后,我們直接操作修改的就是ref對(duì)象上的value屬性,因?yàn)檫@個(gè)契約的存在,以至于在修改屬性值的時(shí)候?qū)?yīng)的源數(shù)據(jù)參數(shù)也會(huì)連同被修改,但在原數(shù)據(jù)被修改之前vue就會(huì)監(jiān)聽(tīng)到我們修改了數(shù)據(jù),立馬進(jìn)行解析模板更新頁(yè)面,這就是ref對(duì)象的響應(yīng)式原理。這里的契約其實(shí)就是Object.defineProperty的get()和set(),篇幅有限我們不對(duì)底層核心代碼做示范.

我們知道了ref函數(shù)定義基本類型,下面會(huì)講解reactive函數(shù),該函數(shù)參數(shù)是對(duì)象類型和ref的對(duì)象類型參數(shù)有著千絲萬(wàn)縷的聯(lián)系,所以學(xué)會(huì)reactive函數(shù)學(xué)會(huì)了ref函數(shù)存儲(chǔ)的對(duì)象數(shù)據(jù)類型也就自然理解了。

reactive函數(shù)

語(yǔ)法:

復(fù)制const xxx=ref(源對(duì)象)

接受的數(shù)據(jù)類型:對(duì)象類型

作用:

把參數(shù)加工成一個(gè)代理對(duì)象,全稱為proxy對(duì)象

核心原理:

基于Es6的Proxy實(shí)現(xiàn),通過(guò)代理操作源對(duì)象,相比于reactive定義的淺層次響應(yīng)式數(shù)據(jù)對(duì)象,reactive定義的是更深層次的響應(yīng)式數(shù)據(jù)對(duì)象。

reactive對(duì)于對(duì)象類型的參數(shù)

基本使用:

復(fù)制?

姓名:{{Person.name}}

?

薪水:{{Person.job.salary}}

import {reactive} from 'vue'export default {? setup(){? ? const p ={? ? ? name:'Ben',? ? ? job:{? ? ? ? salary:'30k'? ? ? }? ? }? ? const Person =reactive(p)? ? return{? ? ? Person? ? }? }}

這里不同于上面的ref函數(shù),參數(shù)是一個(gè)對(duì)象類型的數(shù)據(jù),那么對(duì)于接受返回值的Person對(duì)象也會(huì)和上面的ref對(duì)象一樣都是把數(shù)據(jù)對(duì)應(yīng)到value屬性上嗎?帶著這個(gè)疑問(wèn)打印一下Person對(duì)象:

復(fù)制Proxy[[Handler]]: Object[[Target]]: Objectjob: {salary: "30k"}name: "Ben"[[Prototype]]: Object[[IsRevoked]]: false

我們發(fā)現(xiàn)Person對(duì)象身上并沒(méi)有value屬性并且Person對(duì)象是一個(gè)proxy類型的對(duì)象,這里我們可以理解為Person是一個(gè)加強(qiáng)版的p對(duì)象,對(duì)于p來(lái)說(shuō)Person是一個(gè)代理對(duì)象,所以我們可以直接訪問(wèn)到自身的屬性,而不是和ref函數(shù)一樣把數(shù)據(jù)對(duì)應(yīng)到value屬性上,所以我們r(jià)eturn出去的Person對(duì)象可以直接放在模板里讀取屬性。

響應(yīng)式原理:

reactive的響應(yīng)式是更加“深層次”的,底層依賴于ES6中的Proxy實(shí)現(xiàn),用reactive函數(shù)加工出來(lái)的對(duì)象都是Proxy對(duì)象,無(wú)論原數(shù)據(jù)對(duì)象里面有多少層對(duì)象他們都會(huì)被加工成Proxy類型對(duì)象(深層次)。它的響應(yīng)式核心思想和ref是大同小異的,這里我們定義的Person對(duì)象來(lái)代理p對(duì)象,二者也會(huì)建立“契約”,我們?cè)诎裀erson對(duì)象return出去后,在我們操作修改Person對(duì)象的數(shù)據(jù)時(shí),在原對(duì)象數(shù)據(jù)改變之前Vue都會(huì)監(jiān)聽(tīng)到這一舉動(dòng)并且同時(shí)解析模板、更新頁(yè)面。

Ref函數(shù)對(duì)于對(duì)象類型的參數(shù)

說(shuō)到這里大家會(huì)有個(gè)疑問(wèn),ref定義對(duì)象類型的數(shù)據(jù)和這個(gè)reactive函數(shù)有什么關(guān)系呢?

ref對(duì)象只能去操作淺層次的數(shù)據(jù),把基本數(shù)據(jù)類型當(dāng)做自己的屬性值,如果ref函數(shù)的參數(shù)是對(duì)象這種深層次的數(shù)據(jù)類型時(shí)它會(huì)求助一個(gè)人,這個(gè)人不是別人正是reactive函數(shù),在底層Vue會(huì)把對(duì)象參數(shù)通過(guò)reactive函數(shù)加工成一個(gè)Proxy代理對(duì)象放到ref的value屬性上。

復(fù)制?

姓名:{{Person.name}}

?

薪水:{{Person.job.salary}}

import {reactive,ref} from 'vue'export default {? setup(){? ? const p ={? ? ? name:'Ben',? ? ? job:{? ? ? ? salary:'30k'? ? ? }? ? }? ? const Person =ref(p)? ? console.log(Person)? ? return{? ? ? Person? ? }? }}

打印Person對(duì)象的結(jié)果:

復(fù)制RefImpl {_shallow: false, __v_isRef: true, _rawValue: {…}, _value: Proxy}__v_isRef: true_rawValue: {name: "Ben", job: {…}}_shallow: false_value: Proxy {name: "Ben", job: {…}}value: Proxy[[Handler]]: Object[[Target]]: Objectjob: {salary: "30k"}name: "Ben"[[Prototype]]: Object[[IsRevoked]]: false[[Prototype]]: Object

我們可以很清楚的看到,value屬性下對(duì)應(yīng)的正是給p原數(shù)據(jù)對(duì)象加工生成Proxy對(duì)象。

區(qū)別

存儲(chǔ)類型:ref對(duì)象可以接受基本數(shù)據(jù)類型得數(shù)據(jù)也可以接受對(duì)象類型的數(shù)據(jù),而reactive只可以接受對(duì)象類型的數(shù)據(jù);

響應(yīng)式:相比于ref對(duì)象reactive函數(shù)是更深層次的,ref函數(shù)參數(shù)為對(duì)象類型時(shí)依賴的也是reactive函數(shù);

用法:Proxy代理對(duì)象的數(shù)據(jù)鍵值對(duì)是和原數(shù)據(jù)對(duì)象的鍵值對(duì)一一對(duì)應(yīng)的,在使用時(shí)可以直接使用 對(duì)象(接受返回值的對(duì)象).鍵名 的形式,ref對(duì)象會(huì)把數(shù)據(jù)參數(shù)對(duì)應(yīng)到自己;

value屬性上,在模板里我們可以直接省略.value的形式,這看起來(lái)好像是“把源數(shù)據(jù)賦值給了ref類型的變量,可以直接在模板上使用這個(gè)ref類型的變量”;

響應(yīng)式原理:ref的響應(yīng)式原理是依賴于Object.defineProperty()的get()和set()而reactive的響應(yīng)式原理是依賴于ES6中的Proxy。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容