簡單聊下 Vue3 中 reactive 和 ref


介紹

眾所周知,vue3 相較於 vue2 進行了很大提升,很大的一方面就是響應式原理上————使用了 Proxy。Proxy 可以先看看 阮一峰大大的教程,建議 15、16章節連起來看,那么如何去使用呢?

我們可以這樣的理解,reactive 和 ref 相當於一個語法糖,使用這兩個語法糖創建的變量就具備了響應式的功能,能自動的在頁面和數據之間進行驅動。可能有朋友不太理解,ref 在 vue2 中不是定義操作 DOM 的節點嗎?為什么這里能定義變量了,還是響應式的。這是因為 vue3 內部給它重新進行了賦能,大家先簡單這樣記下就好。

好,具體說下區別:

定義上:

  • ref - 推薦定義基礎類型變量,這個時候內部是使用 Object.defineProperty 實現響應原理的,如果定義了 Object 類型變量,那么其內部還是指向 proxy 的,這點我們可以先打印看看
    ref變量
    控制台

從 value 指向上我們可以看到內部 value、_value 的變更

  • reactive - 推薦使用復雜變量,如 object,可從 ref 定義復雜變量內部還是指向 proxy,或 proxy 攔截復雜對象反向推到,這里放一張 vue3 官方網站上的 reactive 定義
function reactive<T extends object>(target: T): UnwrapNestedRefs<T>

可以看到可拓展對象還是指向的 object

使用方式上:

注意:這里如果沒有特指,使用范圍全部在 setup 內

  • ref - 的賦值必須使用 .value,這點可從打印的圖片上可以看出,那同理,取值的話也要加一個 .value,不然指向不正確,來張圖:

打印
操作

但是 .value 取值的話一次還好,多次就比較麻煩,這里有一個簡化的 api——unref,同樣來張圖:

打印

import { unref } from 'vue';

const aa = ref('haha');
console.log('aa', aa);
console.log('aa.value prev', aa.value);
aa.value = 'houhou';
console.log('aa.value next', aa.value);
console.log('unref(aa)', unref(aa));
  • reactive - reactive 則沒這么麻煩,和正常的 object 一樣操作就好,沒有什么 .value,同樣來張圖:

打印

import { reactive} from 'vue';

const cc = reactive({
  a: 1,
  b: 2,
  c: 3
});
cc.a = 10;
cc.d = 12;
console.log('cc', cc);
console.log('cc.a', cc.a);
console.log('cc.d', cc.d);

可以看到正常的 object.key 這種形式,新增和修改都是能正常響應的(如更改的屬性 a 和 新增的屬性 d),來說說如果對它解構的話會怎樣,來張圖:

打印

let { a } =cc;
console.log('a prev', a);
a = 15;
console.log('a next', a);
console.log('cc', cc);

可以看到,解構的變量不再具有響應式(a 改變,cc 並沒變),當然這種情況用到的不多,如果我們要改變一個對象的某個屬性,一般可通過 Object.assign(obj, {}) 這種形式解決,這里說他只是為了引入 toRefs 這個 api——把 reactive 解構為一組具備響應式關系的 ref,同樣來張圖:

打印

可以看到打印出來的變量 b 已經指向了 ObjectRefImpl 這個類,並看到 ``__v_isRef:、_key、_object、value``` 這幾個屬性,可以簡單的把它們理解為響應關聯,此時 b 這個變量就和 cc 這個對象關聯起來了,當改變 b 的值時,cc 同樣發生了變化,這樣有個好處就是,當我們在一個 reactive 里定義了很多變量時,如果在模板上一個一個 object.key 這種方式去寫,會很麻煩,也不美觀,這個時候就可以 toRefs 出去,直接寫 key 即可,這樣數據就具備了響應關聯,vue 就能在數據變化時自動更新頁面,我們來試下,同樣上圖:

頁面

// template
<ul>
  <li>我是 cc 對象的屬性 a,{{ a }}</li>
  <li>我是 cc 對象的屬性 b,{{ b }}</li>
  <li>我是 cc 對象的屬性 c,{{ c }}</li>
</ul>

// setup
return {
  ...toRefs(cc)
};

最后

說得多還不如上手,大家動手練練哈哈


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM