Vue3 - 關於響應式資料

tags: Vue
category: Front-End
description: Vue3 - 關於響應式資料
created_at: 2022/07/16 11:30:00

cover image


回到 手把手開始寫 Vue3


前言

還是假設你已經做好了第一篇做的事 開新專案與環境設定

在這邊就和 Vue2 差滿多了。


先講講 Vue2 怎麼定義

這邊一樣不負責任的憑感覺打,所以可能不能跑XD

const app = new Vue({
  data: {
    count: 0
  }
})

// or

export default {
  data() {
    return {
      count: 0
    }
  }
}

上面這種方式建立資料的話,Vue 會幫你包裝,如果我沒記錯的話,你把他 console.log 印出來看,他會是一個被 Observe 物件包住的資料,代表那個資料是有被觀測的(或是說具有響應式(Reactivity)的)

而在前端框架,其中一點就是想讓你不要一直頻繁自己操作 DOM,又麻煩(?)又慢,希望你只要好好注重這些資料的邏輯,當資料變動,畫面就立刻更新。

所以有時候新手亂在 methods 之類的地方自己亂新增資料,就會導致那些新新增的資料並不具有響應式,導致畫面上用到卻不會即時更新。

不過還是有新增的方式,印象中是 $set ? (不管 反正現在用不到了(?))

而在 vue3 還是支援上面那樣的定義方式,不過前面文章也提到了,建議使用新的 API 寫法


看看 Vue3 怎麼定義

這邊我就確定可以跑了XD,畢竟主題的品質還是要顧(?)

<script setup>
  import { reactive, ref } from "vue";
  const count = ref(0);
  const data = reactive({ count: 0 });
</script>

<template>
  {{ count }}
  {{ data }}
</template>

這邊你會看到畫面上印出

0 { "count": 0 }

而要怎麼去驗證他是響應式(Reactivity)資料呢?

基本上你隨便寫個方式在事後改變資料,看畫面有沒有更改就知道了,所以寫一段計時器

setTimeout(() => {
  count.value = 100;
  data.count = 100;
}, 1000);

你會發現畫面上的東西在一秒後變成這樣

100 { "count": 100 }

當然也有對應的輔助函數可以判斷

<script setup>
import { isReactive, isRef, reactive, ref } from "vue";
const count = ref(0);
const num = 100;

const data = reactive({ count: 0 });
const obj = { count: 100 };

console.log("count is Ref? ", isRef(count));
console.log("num is Ref? ", isRef(num));
console.log("data is Reactive? ", isReactive(data));
console.log("obj is Reactive? ", isReactive(obj));
</script>

你會看到這樣的輸出

count is Ref?  true
num is Ref?  false
data is Reactive?  true
obj is Reactive?  false

ref VS reactive

這兩個都是宣告出有響應式的資料,那這兩個到底有什麼差別?

我這邊就直接跳過講古那一段了,就是關於 Vue2 使用 Object.defineProperty()Vue3 使用 Proxy(),這個有興趣的自己去爬文(網路上應該有很多)

所以就只單就這兩個語法的差異來說

  • reactive: 只能存物件類型、集合,例如 ArrayObjectMapSet,不能存一般型態,例如 StringNumberBoolean

  • ref: 什麼都可以存,但是通常如果是上面提到 reactive 可以存的就會使用 reactive,而只有一般型態會使用 ref

如果只看上面這兩段,你可能會覺得那就統一 ref 就好了啊,幹嘛這麼麻煩?

因為他們的實作方式不太一樣,而 reactive 又有再做一點點的語法糖

從上面計時器那段應該也可以稍微看出兩者使用方式的差異,在 ref 宣告的需要使用 .value 來設定值,而 reactive 宣告的則直接設定即可。

意思就是說,如果你拿 ref 來宣告一個物件,那寫起來會有稍微一點點麻煩

const data = ref({ count: 0 });

setTimeout(() => {
  data.value.count = 100; // <-- 這行是對的
  data.count.value = 100; // <-- 這行是錯的
}, 1000);

可以看到說因為他是一個 ref 物件,他必須先以 .value 拿到值,也就是拿到 { count: 0 } 之後在更改。

所以 ref 一般通常拿來宣告一般型態,而 reactive 為什麼不用下 .value 呢?

因為它會自動幫你解開(也就是幫你加的感覺),怎麼做實驗呢?

const data = reactive({ count: ref(0) });

setTimeout(() => {
  data.count = 100;
}, 1000);

看看上面這一段,因為他有幫忙解開 .value,否則應該要寫 data.count.value 才會有作用。


總結

所以如果是一般的型態,就使用 ref ,否則就使用 reactive

然後也不要覺得,那到底什麼時候要用物件什麼時候要用一般型態,這就看你的規劃了,例如一個使用者,你可以

const name = '小明'
const username = 'user01'
const email = '[email protected]'

也可以

const user = {
  name: '小明',
  username: 'user01',
  email: '[email protected]'
}

所以我是覺得不用想太多,你喜歡哪個就用哪個,滿直覺的。




最後更新時間: 2022年07月16日.