2023年度鐵人_[Day 13] vue的響應式介紹_ref()及reactive()

 

vue本身這套框架提供了完整的responsive資料即時連動更新機制。

什麼是響應式?
響應式白話來說就是當某變數在其它地方修改之後,任何在修改之前引用到此變數的地方都會隨之改變。

寫過jquery或用純javascript寫過事件的就知道,預設純js/jquery是不支援即時連動更新機制。你需要寫很多dom操作的行為。

Vue 有提供這麼一個方法叫做 watchEffect()方法,幫助我們實踐響應式更新 DOM元素。

新增一個Responsive.vue 組件檔案
https://ithelp.ithome.com.tw/upload/images/20230922/20107452ye8vH1iCwu.png

只先寫以下程式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<!-- eslint-disable --> 
<script setup>
    import { ref, watchEffect } from 'vue'
    const count = ref(0)
    //監聽count值的改變
    watchEffect(() => {
    document.body.innerHTML = `累計計數:${count.value}`;
    })

    count.value = 2; //更新count的值,來間接觸發重新運算連動回饋到DOM。
</script>

在此一開始先將ref跟watchEffect兩個模組引入進來。
使用 const count = ref(0)定義 count 常數,並使用 ref 表示這是一個響應式變數,並初始為 0。
watchEffect後面補上一個call back函數,即時監聽和更新DOM。

count.value = 2;則代表之後的任意地方只要有修改值,就會通知給 body 上的HTML template,從而更新 count 變數值,藉此達到更新 DOM 的目的。

將Responsive.vue 組件import到 App.vue 裏頭渲染。


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<template>
  <main>
    <Responsive/>
  </main>
</template>

<script setup>
  import Responsive from './components/Responsive.vue';

</script>


https://ithelp.ithome.com.tw/upload/images/20230922/20107452lnKuMS2weJ.png
如上圖結果已經將變更為2的結果更新到 DOM 上了,
若使用事件更新 count 變數的值,就會即時的同步更新到 body 元素上。

在此我們來修改程式變更Responsive.vue來模擬事件更新DOM行為

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<!-- eslint-disable --> 
<template>
    <div>
        <span>{{count}}</span>
    </div>
    <div>
        <input type="button" @click="editCount()" value="累加1" />
    </div>
</template>
<script setup>
    import { ref } from 'vue'
    const count = ref(0)
    count.value = 2; //更新count的值,來間接觸發重新運算連動回饋到DOM。

    function editCount(){
        //更新count的值,來間接觸發重新運算連動回饋到DOM。
        count.value++;
    }
</script>


可以看到從一開始初始的2被我連按累加到12...
https://ithelp.ithome.com.tw/upload/images/20230922/201074527MoTq6S0L4.png

小叮嚀:在js中所謂const修飾代表常數後期不允許被修改,但在此使用的是響應式變數,是能夠藉由.value來做值變更的,這邊你也可以將const更改為let也一樣效果。這邊的ref十分重要若省略沒有將變數標記為響應式就不能連動更新。

前面篇章也提及到雙花括號 {{}} 是支援響應式的,因此可以即時反饋出 count 變數的值。


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<!-- eslint-disable --> 
<template>
    <div>
        <span>{{count}}</span>
    </div>
    <div>
        <input type="button" @click="editCount()" value="累加1" />
    </div>
</template>
<script setup>
    //import { ref } from 'vue'
    let count = 0;
    //count.value = 2; //更新count的值,來間接觸發重新運算連動回饋到DOM。

    function editCount(){
        //更新count的值,來間接觸發重新運算連動回饋到DOM。
        //count.value++;
        count++;
    }
</script>


這邊可看到連按都不會有效果,此時的count就不屬於響應式了,DOM始終如一是預設的0。

https://ithelp.ithome.com.tw/upload/images/20230922/20107452UbaSjfxfLn.png

而若變數沒用ref()來定義,變數存取不需要用.value屬性做值的存取。
主要是ref底層是把變數封裝成一個引用的物件,而物件中的值存取是需要透過value的。

小叮嚀:ref()的底層原理是把傳入的參數值包裝為一個帶有.value 屬性的ref物件。
換言之,將值型別透過 ref()包裝成參考型別,如此一來值型別就會具有響應特性,相應的值都必須透過.value 做寫入及讀取。

還有一個和ref()有點像的叫做reactive()
相較於ref()方法可使用任何值型別,reactive()只能使用參考型別。

JS 中的參考型別,大都可以使用 reactive()函數定義,可以創建一個響應式的物件或陣列、Map、Set等等集合型別。
因此若是像number,boolean,string這類的型別是無效的。

我們微調程式來測試後

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<!-- eslint-disable --> 
<template>
    <input type="button" @click="getData" value="獲取" />
    <span>{{student.name}}</span>
</template>
<script setup>
    import { reactive } from 'vue'
    const student = reactive({ name: 'Mike', age: 25, sex: '男' });
    
    const getData = () => {
        student.name = 'Jackson';
    };
</script>


基本上就是從一開始Mike點按後更新此student物件中的name屬性
https://ithelp.ithome.com.tw/upload/images/20230922/201074529bkwM0E1b7.png

以上就是ref跟reactive兩者差異。





留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

經得起原始碼資安弱點掃描的程式設計習慣培養(五)_Missing HSTS Header