iT邦幫忙

2021 iThome 鐵人賽

DAY 28
0
Modern Web

前端暴龍機,Vue2.x 進化 Vue3系列 第 28

[前端暴龍機,Vue2.x 進化 Vue3 ] Day28.Vue3 小補充 Magic ~

https://ithelp.ithome.com.tw/upload/images/20210825/20120722BU3BxcILPM.jpg
下面來介紹一下,Vue 3 的一些小小魔法(個人覺得很 Magic ~ 哈哈),
有些是補充說明,
有些可能會很少使用到,就連官方都有提醒 " 請謹慎使用 "
至於要不要使用,我覺得還是看個人或者專案需求 (我也覺得有點複雜 /images/emoticon/emoticon16.gif)

Composition API 的高度彈性

還記得 Composition API 讓我們撰寫的彈性變得非常大,我們可以將相同的資料與處理邏輯寫在同一個區塊,所以其實像是生命週期鉤子這類的也一樣,假如 A 的處理邏輯會在 onMounted 觸發, B 的處理邏輯也會在 onMounted 觸發,所以我們的 onMounted 是允許可以分別寫在兩個區塊,範例如下 :

createApp({
  setup() {
    
    // A 的相關處理邏輯
    const A = ref("A");
  
    function Afunc(){
      // ...
    }
    
    onMounted(()=>{
     Afunc()
    })
    
    // B 的相關處理邏輯
    const B = ref("B");
  
    function Bfunc(){
      // ...
    }
    
    onMounted(()=>{
     Bfunc()
    })
    
    return {
      A,
      Afunc,
      B,
      Bfunc
    }
  }
}).mount('#app')

深層監聽

記得前面有提過 ref 不會對物件或陣列內部的屬性變動做監聽,又或是其它某些狀況,我們需要自己寫監聽器

在 Vue2 的寫法

data:{
    todos:[]
},
watch : {
    todos:{
        deep: true,
        handler() {
            // do something ...
        }
    }
}

在 Vue3 的寫法

watch(要被監聽的變數, ()=>{
    // 監聽到變更時要做的事
},
{deep:true }
)
const todos = ref([]);
watch(todos,()=>{
  // do something ...
},
{deep:true}
)

寫法看似很像,不過當初在寫的時候,轉換不過來/images/emoticon/emoticon06.gif
而且記得不太好找,所以這邊稍作補充 ( 哈哈,也可能我的搜尋能力待加強~~

isRef & isReactive

這兩個感覺是滿好玩的,不過目前我想不出來可以在日常的甚麼地方使用 @@
isRef : 判斷是不是透過 ref 建立出來的
isReactive : 判斷是不是透過 reactive 建立出來的

import {createApp,ref,reactive,onMounted,isReactive,isRef} from 'https://cdnjs.cloudflare.com/ajax/libs/vue/3.1.4/vue.esm-browser.min.js' 

createApp({
  setup() {
    
    const AA = ref({name:"ref"});
    const BB = reactive({ name: "reactive"});

    onMounted(()=>{
      console.log("AA is ref ? ===> ",isRef(AA))
      console.log("AA is isReactive ? ===> ",isReactive(AA))
      console.log("BB is ref ? ===> ",isRef(BB))
      console.log("BB is isReactive ? ===> ",isReactive(BB))
    })

    return {
      AA,
      BB
    }
  }
}).mount('#app')

https://ithelp.ithome.com.tw/upload/images/20210825/20120722Ms0jMhdbba.jpg
演示範例

小心使用的魔法 toRaw

  • 從 Reactive 或 Ref 中得到 原始資料
  • 做一些不想被監聽的事情(提升效能 : 因為不會變動就更新畫面)
    https://ithelp.ithome.com.tw/upload/images/20210825/20120722mBxWFiEbgz.jpg
    從圖中,我們可以看到下面幾點
  1. toRaw 出來的跟 reactive 建立是有差異的 (不符合 "==="),所以就沒有了雙向
  2. toRaw 出來的跟 原始資料相等 (符合 "===")
  3. 變更 reactive 內容,三者資料一起更新,並且更新畫面
  4. 變更 toRaw 內容,三者資料一起更新,但是沒有更新畫面

https://ithelp.ithome.com.tw/upload/images/20210825/201207223ZrcuW154q.jpg
另外,如果是使用 ref 建立的,需要加上 .value 才會拿到原始資料

toRaw 演示範例

toRaw
返回 reactive 或 readonly 代理的原始对象。这是一个转义口,可用于临时读取而不会引起代理访问/跟踪开销,也可用于写入而不会触发更改。不建议保留对原始对象的持久引用。请谨慎使用。
《 Vue3 官方文件 - toRaw 》

魔法 toRefs

将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的ref。
《 Vue3 官方文件 - toRefs 》

可以將響應式的物件,轉換為普通的物件,而物件內的 keyValue 都會被包裝成 ref 的型態
https://ithelp.ithome.com.tw/upload/images/20210826/20120722MnjnbmF5WF.jpg

所以啦~ 一開始 開開心心的,想舉跟 toRaw 類似的例子,將普通物件reactive 物件ref 物件 通通拿來做 toRefs,結果沒想到錯了 /images/emoticon/emoticon04.gif

import {createApp,ref,reactive,onMounted,toRefs} from 'https://cdnjs.cloudflare.com/ajax/libs/vue/3.1.4/vue.esm-browser.min.js' 

createApp({
  setup() {
    
    // 原始數據
    const obj = {
        name: '小智媽媽',
        age: 18,
        gender: "female"
    }
    
    // 原始數據 toRefs
    const toRefs_obj = toRefs(obj);
    
    // reactive 物件
    const reactive_obj = reactive(obj);
    // reactive toRefs 轉換
    const reactive_toRefs = toRefs(reactive_obj);
    
    // ref 物件
    const ref_obj = ref(obj);
    // ref toRefs 轉換
    const ref_toRefs = toRefs(ref_obj);
    
    return {
    }
  }
}).mount('#app')

https://ithelp.ithome.com.tw/upload/images/20210826/20120722ZL93zsLirK.jpg
會提示你 toRefs 期望接到的資料型態是 reactive 物件,所以響應式對象不包含 ref,那麼只能使用 reactive 作範例~

先來看一下,資料建立完的樣子

https://ithelp.ithome.com.tw/upload/images/20210826/201207221ZdXKUd7BL.jpg

觀察數據之間的關係

https://ithelp.ithome.com.tw/upload/images/20210826/201207223NdPyUJp0b.jpg
結果彼此之間都沒關係 ⟹ 那麼? 所以如果更改資料會有甚麼影響? 會不會觸發介面更新?

資料變動後的變化

1. 更改原始數據 (age: 18 ➛ 16)

https://ithelp.ithome.com.tw/upload/images/20210826/20120722zWEcMVzwHm.jpg
三者的數據全部更新,不過沒更新畫面

2. 更改 reactive (name: 小智媽媽 ➛ 健美中的小智媽媽)

https://ithelp.ithome.com.tw/upload/images/20210826/20120722HYhNgIt05Z.jpg
三者的數據全部更新,而且畫面也都被變動了

3. 更改 toRefs (gender: female ➛ 神的傳說)

https://ithelp.ithome.com.tw/upload/images/20210826/20120722HAyKuU9pO7.jpg
只有 toRefs 值被變更,且畫面皆無更新
而且因為物件內的 keyValue 都會被包裝成 ref 的型態,所以取得 keyValue 值也就必需再加上 .value

<p>toRefs : </p>
<p>{{ reactive_toRefs.name.value }}</p>
<p>{{ reactive_toRefs.age.value }}</p>
<p>{{ reactive_toRefs.gender.value }}</p>

toRefs 演示範例

最後, Vue3 的介紹大致上就介紹到這邊,後面就一起使用 Composition API 來實作我們最後的小專案吧~


圖片來源

Meme 梗圖倉庫,李俐彥 - 魔法卡
維基百科 Vue.js
【MAD】digimon03 數碼暴龍03 進化集 evaluation | YouTube

參考資料

HINA::工程幼稚園 — Vue3 - 每天來一點雷 Part 2
Vue3 官方文件 - toRaw
快速使用Vue3最新的15個常用API
Vue3 官方文件 - toRefs
vue3 之 reactive && toRefs原始碼解析,TW511教學網
Vue3.0學習筆記,程式人生
Vue3.0(四)ref源码分析与toRefs,知乎 - 圈鹅
簡單梳理下 Vue3 的新特性, IT人 - lliiooiill


上一篇
[前端暴龍機,Vue2.x 進化 Vue3 ] Day27. Vue3 ref & reactive 小練習
下一篇
[前端暴龍機,Vue2.x 進化 Vue3 ] Day29.Vue3 網頁小遊戲(一) | ♾ 台版魷魚遊戲,玩?還是不玩?
系列文
前端暴龍機,Vue2.x 進化 Vue330

尚未有邦友留言

立即登入留言