在開始之前,我應該先了解你 - 聊聊vue 3的改動
最近準備用 Vue3 開發新的專案了,趁這個機會順便整理 vue3 與 vue2 有哪些差異, 稍微瀏覽一下新功能和寫法 ,不得不說真的覺得跟 React 好像 XD,當然也有人覺得我幹嘛不學 react 就好了,但花點時間寫過一些 vue3 的練習之後,確實感受到 vue3 參考了不少 React 的優點,但學習曲線更加友善,效能方面也提昇了不少,好 vue3,不學嗎?
以下列舉幾項 vue3 和 vue2 的差異
setup
執行階段會在 beforeCreate 之前,取代了原本得 beforeCreate 和 created,可以想像成是唯一的入口 function,會在這裡初始化 data 宣告 ref 等等..
同時也發現 methods 不見了,所有需要用到的 function 都直接宣告在 setup 裡面即可,跟以往不同的是,用到甚麼功能就要記得從 vue 引入
reactive ({})
reactive 可以傳入一個物件或是陣列,但如果傳入 number,string 等基礎型別就會報錯,因為 Proxy 只接受 object 型別的資料,透過 reactive 才能響應式的偵測資料的變動,所以以往寫在 data 的東西就會改寫在這裡囉!
Lifecycle Hooks
熟悉的 mounted、beforeDestroy…不見了,取而代之的是皆以 on 開頭的 Hooks(onMounted、onBeforeUnmount),並且要記得將生命週期要寫在 setup 函式裡面。
下面附上一張生命週期對照表
emit&props
正當我習慣地寫下
1 | this.$emit("changePage", 5); |
發現我熟悉的 this 不見了!?居然變成了 undefined,所以我說那個 this 呢?稍微翻了一下文件,發現在 setup 裡面已經取不到 this 了,取而代之的是 context,setup 可以傳入兩個參數,props 和 context
直接 console.log context 看看結果
所以我們可以透過 context 取得 attrs、 slots 、emit 等屬性
因此使用 emit 可以有兩種方式
- 透過解構賦值
- 透過 context 呼叫
另外,props 不需要 return 出去 ,就可以直接在 template 使用了
以往我們可以在 props 定義類型 、預設值等等,現在 emit 也可以像 props 一樣列舉有哪些 emit,同時也能針對傳進來的參數做初步的判斷。
Fragments
在 vue2 如果 template 的最外層沒有一個根結點的話就會報錯
The template root requires exactly one element vue/valid-template-root
vue3 終於可以擺脫這個束縛啦!
::v-deep
以往的 deep(scss)
或是>>>(css)
改用::v-deep
取代了
甚麼時候會用到? 當你的 css 需要改動到下一層 component 的樣式
::v-global
終於可以在 style scoped 裡面,寫下全域的樣式了
ref
只能監聽 String 、Number、 Boolean 的變化,當 Array、 Object 內部屬性有變化是沒有辦法監聽的(請用 reactive)
在 setup 裡面 ref 會回傳一個物件,所以必須用 value 屬性來取到值,而在 template 裡 ref 會自動 unwraps 就可以直接取用,不需要.value
假如是要取得 DOM 的話
- 先在 setup 定義一個 ref
- 綁定在想要取得的 DOM 上
- 就可以在 onMounted 階段取得 DOM
toRef
將物件中的屬性變成響應式的數據,但要注意不會觸發畫面的更新,toRef 接收兩個參數 ,第一個對象, 第二個是屬性
如果想要把一個物件的每個屬性都變成響應式的資料,就可以用 toRefs
watch、watchEffect
watch 第一個參數為要監控的值 ,第二個參數傳入 callback function 可以取得新舊值的變化
watchEffect 只要傳入 callback 函式, 在初始化的時候就會先執行一遍 ,會自動監聽在函式裡有用到的值變化
Teleport
想必大家都曾經遇過一個問題 ,假設有 A 、B 兩個 component(B 為 A 的子 component)想要在 B 控制一個彈窗顯示, 就會有層級的問題(z-index) ,無法讓 B 的 z-index 大於 A component, 因此無法達到彈窗的滿板覆蓋效果, 透過 Teleport 我們可以先在自己的 component 定義好內容,並且控制顯示與否,然後渲染到外層的 DOM 上,就像任意門一樣,以後寫彈窗又更方便了
Index.vue
App.vue
Suspense
利用 defineAsyncComponent 來動態載入 component ,在還沒載入前,會先看到 template#fallback 裡面的內容 ,等到 component 載入完畢之後就會顯示#default 的內容。
transition-class
算是把 class 名稱定義的更明確
createApp
vue 的初始化從 new Vue()改成用 createApp
vue2
vue3
定義全域的變數
被移除的項目
- $on, $off ,$once
是的,意謂著我們要跟 event bus 說再見了 - keyCode
在 vue3 裡面使用
1 | <input v-on:keyup.13="submit" /> |
會出現了這段錯誤
KeyboardEvent.keyCode’ modifier on ‘v-on’ directive is deprecated. Using ‘KeyboardEvent.key’ instead
打開 MDN 才發現 KeyboardEvent.keyCode 居然已經變成 deprecated 了!
以上只是很簡略的列出一些差異,要深入了解的話還是建議閱讀官方文件
對了,如果要用 Vue CLI 開發 vue3,記得要先升級 Vue CLI 版本到 4 以上,或是可以搭配 vite 開發
參考資料: https://v3.vuejs.org/
更新於 2022/6
如果以上述的方式寫過一陣子的 vue3 應該都會有一個感想
要一直 return 變數和 function 真的好麻煩阿…
於是就有了<script setup>
這個語法糖誕生,也就是把 setup 直接寫在 script 後面,跟以往不同的是 script 會寫在最上面,接著是 template,最後是 style,重點是…
再也不用 return 了! 超級方便!
defineProps() & defineEmits()
不過改用 script setup 寫法你可能會有一個疑問: 那 props 和 emit 我要從哪裡取得呢? 就靠defineProps & defineEmits 了!
這邊要特別注意defineProps & defineEmits
都不需要自行引入,因為官網有提到
defineProps
anddefineEmits
are compiler macros only usable inside<script setup>
. They do not need to be imported and are compiled away when<script setup>
is processed.
必須說用過 script setup 之後就回不去了,程式碼變得更加簡潔 ,可以少寫很多程式碼,推薦大家有時間可以試試看,更多 script setup 介紹可參考這裡