在開始之前,我應該先了解你 - 聊聊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、beforeDestory…不見了,取而代之的是皆以on開頭的Hooks(onMounted、onBeforeUnmount),並且要記得將生命週期要寫在setup 函式裡面。
下面附上一張生命週期對照表
emit&props
正當我習慣地寫下
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裡面使用
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介紹可參考這裡