Vue3 Composition API(一)——setup、reactive、ref、readonly
一、Options API的弊端
在Vue2中,我們編寫組件的方式是Options API:
- Options API的一大特點就是在對應的屬性中編寫對應的功能模塊;
- 比如data定義數據、methods中定義方法、computed中定義計算屬性、watch中監聽屬性改變,也包括生命周期鉤子;
但是這種代碼有一個很大的弊端:
- 當我們實現某一個功能時,這個功能對應的代碼邏輯會被拆分到各個屬性中;
- 當我們組件變得更大、更復雜時,邏輯關注點的列表就會增長,那么同一個功能的邏輯就會被拆分的很分散;
- 尤其對于那些一開始沒有編寫這些組件的人來說,這個組件的代碼是難以閱讀和理解的(閱讀組件的其他人);
如果我們能將同一個邏輯關注點相關的代碼收集在一起會更 好。 這就是Composition API想要做的事情,以及可以幫助我 們完成的事情。
也有人把Vue CompositionAPI簡稱為VCA。
二、認識Composition API
那么既然知道Composition API想要幫助我們做什么事情,接下來看一下到底是怎么做呢?
- 為了開始使用Composition API,我們需要有一個可以實際使用它(編寫代碼)的地方;
- 在Vue組件中,這個位置就是 setup 函數;
setup其實就是組件的另外一個選項:
- 只不過這個選項強大到我們可以用它來替代之前所編寫的大部分其他選項;
- 比如methods、computed、watch、data、生命周期等等;
接下來我們一起學習這個函數的使用:
- 函數的參數
- 函數的返回值
三、setup函數的參數
setup函數的參數,它主要有兩個參數:
- 第一個參數:props
- 第二個參數:context
props非常好理解,它其實就是父組件傳遞過來的屬性會被放到props對象中,我們在setup中如果需要使用,那么就可以直接通過props參數獲取:
- 對于定義props的類型,我們還是和之前的規則是一樣的,在props選項中定義;
- 并且在template中依然是可以正常去使用props中的屬性,比如message;
- 如果我們在setup函數中想要使用props,不可以通過 this 去獲取
- 因為props有直接作為參數傳遞到setup函數中,所以我們可以直接通過參數來使用即可;
另外一個參數是context,我們也稱之為是一個SetupContext,它里面包含三個屬性:
- attrs:所有的非prop的attribute;
- slots:父組件傳遞過來的插槽(這個在以渲染函數返回時會有作用,后面會講到);
- emit:當我們組件內部需要發出事件時會用到emit(因為我們不能訪問this,所以不可以通過 this.$emit發出事件);
四、setup函數的返回值
setup既然是一個函數,那么它也可以有返回值,它的返回值用來做什么呢?
- setup的返回值可以在模板template中被使用;
- 也就是說我們可以通過setup的返回值來替代data選項;
- 甚至是我們可以返回一個執行函數來代替在methods中定義的方法:
但是,如果我們將 counter 在 increment 或者 decrement進行操作時,是否可以實現界面的響應式呢?
- 答案是不可以;
- 這是因為對于一個定義的變量來說,默認情況下,Vue并不會跟蹤它的變化,來引起界面的響應式操作;
五、setup不可以使用this
官方關于this有這樣一段描述:
- 表達的含義是this并沒有指向當前組件實例;
- 并且在setup被調用之前,data、computed、methods等都沒有被解析;
- 所以無法在setup中獲取this;
六、Reactive API
如果想為在setup中定義的數據提供響應式的特性,那么我們可以使用reactive的函數:
那么這是什么原因呢?為什么就可以變成響應式的呢?
- 這是因為當我們使用reactive函數處理我們的數據之后,數據再次被使用時就會進行依賴收集;
- 當數據發生改變時,所有收集到的依賴都是進行對應的響應式操作(比如更新界面);
- 事實上,我們編寫的data選項,也是在內部交給了reactive函數將其編程響應式對象的;
七、Ref API
reactive API對傳入的類型是有限制的,它要求我們必須傳入的是一個對象或者數組類型:
- 如果我們傳入一個基本數據類型(String、Number、Boolean)會報一個警告:
這個時候Vue3給我們提供了另外一個API:ref API - ref 會返回一個可變的響應式對象,該對象作為一個 響應式的引用 維護著它內部的值,這就是ref名稱的來源;
- 它內部的值是在ref的 value 屬性中被維護的;
這里有兩個注意事項:
- 在模板中引入ref的值時,Vue會自動幫助我們進行解包操作,所以我們并不需要在模板中通過 ref.value 的方式
來使用; - 但是在 setup 函數內部,它依然是一個 ref引用, 所以對其進行操作時,我們依然需要使用 ref.value的方式;
八、Ref自動解包
模板中的解包是淺層的解包,如果我們的代碼是下面的方式:
注意:
最新版本的vue中已經支持在template中直接寫info.message這種方式,一樣可以自動解包
如果我們將ref放到一個reactive的屬性當中,那么在模板中使用時,它會自動解包:
九、readonly的使用
在readonly的使用過程中,有如下規則:
- readonly返回的對象都是不允許修改的;
- 但是經過readonly處理的原來的對象是允許被修改的;
比如 const info = readonly(obj),info對象是不允許被修改的;
當obj被修改時,readonly返回的info對象也會被修改;
但是我們不能去修改readonly返回的對象info;
其實本質上就是readonly返回的對象的setter方法被劫持了而已;
那么這個readonly有什么用呢?
在我們傳遞給其他組件數據時,往往希望其他組件使用我們傳遞的內容,但是不允許它們修改時,就可以使用readonly了;
十、Reactive判斷的API
十一、toRefs
如果我們使用ES6的解構語法,對reactive返回的對象進行解構獲取值,那么之后無論是修改結構后的變量,還是修改reactive返回的info對象,數據都不再是響應式的:
那么有沒有辦法讓我們解構出來的屬性是響應式的呢?
- Vue為我們提供了一個toRefs的函數,可以將reactive返回的對象中的屬性都轉成ref;
- 那么我們再次進行結構出來的 name 和 age 本身都是 ref的;
這種做法相當于已經在info.name和ref.value之間建立了 鏈接,任何一個修改都會引起另外一個變化;
十二、toRef
如果我們只希望轉換一個reactive對象中的屬性為ref, 那么可以使用toRef的方法:
十三、ref其他的API
十四、customRef
創建一個自定義的ref,并對其依賴項跟蹤和更新觸發進行顯示控制:
- 它需要一個工廠函數,該函數接受 track 和 trigger 函數作為參數;
- 并且應該返回一個帶有 get 和 set 的對象;
這里我們使用一個的案例:
- 對雙向綁定的屬性進行debounce(防抖)的操作;
總結
以上是生活随笔為你收集整理的Vue3 Composition API(一)——setup、reactive、ref、readonly的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Web框架——Flask系列之综合案例—
- 下一篇: Vue移动端项目——Vant 移动端 R