1. 程式人生 > 程式設計 >Vue3中ref與reactive的詳解與擴充套件

Vue3中ref與reactive的詳解與擴充套件

目錄
  • 一、ref和reactive
    • 1.reactive
    • 2.ref
  • 二、shallowRef和shallowReactive
    • 1. ref和shallowRef
    • 2. reactive和shallowReactive
  • 三、toRaw
    • 四、markRaw
      • 五、toRef和toRefs
        • 1. ref
        • 2. toRef
        • 3. toRefs
      • 總結

        一、ref和reactive

        死死記住:ref本質也是reactive,ref(obj)等價於reactive({value: obj})

        • 3中實現響應式資料的方法是就是使用ref和reactive,所謂響應式就是介面和資料同步,能實現實時更新
        • vue2中響應式是通過defineProperty實現的,vue3中是通過ES6的Proxy來實現的

        Vue3中ref與reactive的詳解與擴充套件

        1.reactive

        • reactive的引數必須是一個物件,包括on資料和陣列都可以,否則不具有響應式
        • 如果給reactive傳遞了其他物件(如時間物件),預設情況下修改物件介面不會自動更新,如果想更新,可以通過給物件重新賦值來解決

        2.ref

        既然有了reactive,為何還要ref呢?當我們只想讓某個變數實現響應式的時候,採用reactive就會比較麻煩,因此vue3提供了ref方法進行簡單值的監聽,但並不是說ref只能傳入簡單值,他的底層是reactive,所以reactive有的,他都有。還是那句老話:

        死死記住:ref本質也是reactive,ref(obj)等價於reactive({value: obj})

        • 在vue中使用ref的值,不用通過.value獲取
        • 在js中使用ref的值,必須通過.value獲取

        二、shallowRef和shallowReactive

        遞迴監聽和非遞迴監聽
        ref和reactive都屬於遞迴監聽,也就是資料的每一層都是響應式的,如果資料量比較大,非常消耗效能,非遞迴監聽只會監聽資料的第一層。

        1. ref和shallowRef

        • ref定義的資料每一層都是響應式資料
        • shallowRef定義的資料,只有第一層是響應式的,即只有在更改.value的時候才能實現響應式
        let age = ref({
              a: '1',f: {
                b: '2',s:{
                  c: '3'
                }
              }
            })
        //列印各層資料
        console.log(age);
        console.log(age.value);
        console.log(age.value.f);
        console.log(age.value.f.s);
        

        Vue3中ref與reactive的詳解與擴充套件

        let age = shallowRef({
              a: '1',s:{
                  c: '3'
                }
              }
            })
        //列印各層資料
        console.log(age);
        console.log(age.value);
        console.log(age.value.f);
        console.log(age.value.f.s);
        

        Vue3中ref與reactive的詳解與擴充套件

        使用shallowRef後,可以通過triggerRef()方法主動更新介面,實現介面重新整理

        function doSome(){
          age.valuwww.cppcns.come.f.s.c = 'c';
          //主動更新介面
          triggerRef(age);
        }
        

        2. reactive和shallowReactive

        Vue3中ref與reactive的詳解與擴充套件

        注意:shallowReactive沒有類似triggerRef()的方法

        三、toRaw

        toRaw的出現是解決什麼問題呢?

        有些時候我們不希望資料進行響應式實時更新,可以通過toRaw獲取ref或reactive引用的原始資料,通過修改原始資料,不會造成介面的更新,只有通過修改ref和reactive包裝後的資料時才會發生介面響應式變化。

        let obj1 = {...};
        //state和obj1是引用關係,state的本質是一個Proxy物件,其中引用了obj1
        let state = reactive(obj1);
        //通過toRaw方法獲取到原始資料,其實是獲取到obj1的記憶體地址,obj2和obj1是完全相等的
        let obj2 = toRaw(state)
        console.log(obj1 === obj2);//true
        

        有些同學會問,那直接使用obj1來修改資料不就行了嗎?可關鍵是我們在使用reactive定義資料時一般不會先定義一個obj,再將他傳給reactive,都是直接在reactive中寫資料的。

        四、markRaw

        與toRaw不同,markRaw包裝後的資料永遠不會被追蹤!

        暫時沒發現有什麼用處(手動狗頭)

        let obj1 = {name: "lijing",age: 18}
        let obj2 = markRaw(obj1);
        //此時reactive包裝的資料雖然是響應式物件,但是不會被跟蹤,也不會產生www.cppcns.com效應式效果
        let state1 = reactive(obj2)
        
        console.log(obj1 === obj2);//true
        

        五、toRef和toRefs

        ref和toRef都是用來構造響應式資料,兩者有什麼區別呢,看兩個例子

        1. ref

        複製,修改響應式資料不會影響以前的資料,資料發生改變介面就會自動更新

        轉換後的是一個RefImpl型別

        Vue3中ref與reactive的詳解與擴充套件

        可以看到,使用ref對一個物件的某個簡單資料型別屬性進行響應式改造後,通過修改響應式資料不會影響到原始資料,如上圖中,通過state1修改值後,obj1中的a屬性值沒有發生變化。這裡有個注意點:修改的這個屬性必須是簡單資料型別,一個具體的值,不能是引用,如果該屬性也是一個物件,則會影響,因為物件--->引用!

        例如上面例子中,如果傳入state1的是obj1.f,則情況完全不同

        //等價於let state1 = ref({b: '2',s: {c: '3'}})
        // 又等價於--->let state1 = reactive(lGzQsmBU{value: {....}}})
        let state1 = ref(obj1.f);
        

        2. toRef

        如果使用toRef來轉換,則修lGzQsmBU改響應式資料會影響到原始資料,資料發生改變,但是介面不會自動更新

        轉換後的是一個ObjectRefImpl型別

        Vue3中ref與reactive的詳解與擴充套件

        ref類似深拷貝,toref類似淺拷貝

        3. toRefs

        遍歷物件中的所有屬性,將其變為響應式資料,這是因為toRef只能傳一個key,toRefs所達到的效果與toRef一樣

        Vue3中ref與reactive的詳解與擴充套件

        tips:目前用的最多的還是ref和reactive,其他東西一般是後期用來改善效能使用的。

        總結

        到此這篇關於Vue3中ref與reactive的文章就介紹到這了,更多相關Vue3 ref與reactive內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!