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

ref函數(shù)

語法:

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

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

作用:

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

核心原理:

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

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

基本使用:

復(fù)制?

{{Str}}

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

上面我們定義了一個(gè)Str變量來接收ref加工生成的ref對象,我們都知道對象的數(shù)據(jù)都是以鍵值對的形式存儲的,但是在這里為什么直接把Str給return出去, 并且模板里可以直接寫Str這個(gè)對象呢,我們的源數(shù)據(jù)呢?帶著這個(gè)疑問我們來輸出一下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對象身上的一個(gè)屬性?value,沒錯(cuò),我們存入的值就對應(yīng)在value屬性上,至于為什么直接return出是Str而不是Str.value。是因?yàn)閂ue幫了我們一個(gè)忙,我們在這里可以簡寫,return出去的Str就相當(dāng)于Str.value,當(dāng)然,非要寫.value的形式也不是不可以。不過這里需要注意的是,在setup函數(shù)中操作Str中的數(shù)據(jù)不可以簡寫。

響應(yīng)式原理:

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

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

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

reactive函數(shù)

語法:

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

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

作用:

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

核心原理:

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

reactive對于對象類型的參數(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è)對象類型的數(shù)據(jù),那么對于接受返回值的Person對象也會和上面的ref對象一樣都是把數(shù)據(jù)對應(yīng)到value屬性上嗎?帶著這個(gè)疑問打印一下Person對象:

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

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

響應(yīng)式原理:

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

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

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

ref對象只能去操作淺層次的數(shù)據(jù),把基本數(shù)據(jù)類型當(dāng)做自己的屬性值,如果ref函數(shù)的參數(shù)是對象這種深層次的數(shù)據(jù)類型時(shí)它會求助一個(gè)人,這個(gè)人不是別人正是reactive函數(shù),在底層Vue會把對象參數(shù)通過reactive函數(shù)加工成一個(gè)Proxy代理對象放到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對象的結(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屬性下對應(yīng)的正是給p原數(shù)據(jù)對象加工生成Proxy對象。

區(qū)別

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

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

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

value屬性上,在模板里我們可以直接省略.value的形式,這看起來好像是“把源數(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)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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