對於沒太瞭解 Vue3.0 的同窗,在看到 Composition API 時,除了看起來會有一個「高大上」的感受,可能更多的是有點懵逼,心中難免泛起一堆疑惑,這究竟是何方神聖?幹了何等大事?承擔了何種重任?javascript
下面咱們就一塊兒來簡明扼要聊聊,用人人都聽得懂的話來闡述 Vue3.0 Composition API。前端
首先,這兩單詞是啥意思?vue
Composition: 構成,組合方式java
API:應用程序接口(Application Programming Interface),指一些預先定義的函數,用來系統之間、組件之間、函數之間交互的一種約定。web
說人話,在 Vue3.0 中是什麼意思呢?api
中文名:合成函數微信
「 以函數爲載體,將業務相關的邏輯代碼抽取到一塊兒,總體打包對外提供相應能力,這就是 Composition API 」less
能夠理解它是咱們組織代碼,解決邏輯複用的一種方案。編輯器
那 Vue3.0 中爲何要以函數爲載體,將業務相關代碼抽取到一塊兒呢?函數
咱們來看下當前的 Vue2.x 的代碼組織方式:
export default {
props: {
……
},
data() {
return {
……
};
},
watch: {
……
},
computed: {
……
}
methods: {
……
}
複製代碼
上述是咱們再熟悉不過的寫法了,在一個組件當中實現某一個功能,可能會有如下幾個代碼塊:
按照這種方式寫完代碼後,假如是其餘人來看這代碼,會是什麼狀況呢?
若是須要查找某個功能的邏輯,就須要在這個組件中,不斷的滾動頁面去查看各個模塊的的代碼,若是代碼邏輯很複雜的,跳來跳去,看的着實真叫一個難受呀!
這就是當前 Vue2.x 的組織代碼形式,叫 Options API,形象以下圖(只需關注顏色塊區域位置):
圖中相同顏色區域表明同一個功能模塊,這裏給人感受是整個組件代碼比較凌亂,功能代碼塊交錯出現,顏色相互穿插,眼花繚亂。
可能有同窗會說了,你這個是基本用法,咱們能夠用 Mixins,HOC,Renderless Components 來規避這種問題呀。
You are right ! 這些必定程度上是能夠解決這個問題,可是他們都或多或少存在一些問題:
模版中的數據來源不清晰。舉例來講,當一個組件中使用了多個 mixin 的時候,光看模版會很難分清一個屬性究竟是來自哪個 mixin。HOC 也有相似的問題。
命名空間衝突。由不一樣開發者開發的 mixin 沒法保證不會正好用到同樣的屬性或是方法名。HOC 在注入的 props 中也存在相似問題。
性能。HOC 和 Renderless Components 都須要額外的組件實例嵌套來封裝邏輯,致使無謂的性能開銷。
另外,將 Vue2.x 現有的 API 在與 Typescript 集成時的確有一些挑戰,主要是由於 Vue 依賴於 this 上下文來拋出屬性,並且相較於簡單的 JavaScript,this 在 Vue 組件中有不少魔法性 (好比:methods 屬性裏面定義的函數裏的 this 指向的是組件實例,而不是 methods 對象)。
除了以上幾個緣由外,Composition API 還有兩個優點:
類型推導:基於函數的 API 自然對類型推導很友好,由於 TS 對函數的參數、返回值和泛型的支持已經很是完備。
打包尺寸:基於函數的 API 每個函數均可以做爲 named ES export 被單獨引入,這使得它們對 tree-shaking 很是友好。同時,由於全部的函數名和 setup 函數體內部的變量名均可以被壓縮,因此擁有更好的壓縮效率。
基於各方權衡,因此整出了 Composition API。
說了這麼多,那麼 Composition API 在哪裏使用呢?
咱們要知道 Composition API 是代碼邏輯組合和複用的方案,不是替代組件的方案。換言之,原來組件該怎麼劃分,如今繼續怎麼劃分,絲絕不受影響。
可是組件內的代碼的組織,組件間代碼的複用,則和 Composition API 息息相關,好比以下:
listenMouse.js
import { ref, onMounted, onUnmounted } from 'vue'
function useMouse() {
const x = ref(0)
const y = ref(0)
const update = e => {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() => {
window.addEventListener('mousemove', update)
})
onUnmounted(() => {
window.removeEventListener('mousemove', update)
})
return { x, y }
}
export default useMouse;
複製代碼
這裏將 變量定義 x, y,生命週期函數 onMounted,onUnmounted,更新方法 update 都集成到一塊了,以函數 useMouse 爲載體,統一對外提供監聽鼠標位置的 API 服務。因而在任何的組件中均可以使用到該服務,不受限制。
以下在組件中使用 listenMouse 提供的服務:
<template>
<p>Mouse Position:</p>
<p>x:{{ x }},y:{{ y }}</p>
</template>
<script> import useMouse from './listenMouse'; export default { setup (props) { let {x, y} = useMouse(); return { x, y } } } </script>
複製代碼
使用 Composition API 的方式,你會發現邏輯複用超簡單了,且超清晰,代碼更整潔,形象以下圖(只需關注顏色塊區域位置):
這裏相同顏色區域表明同一個功能模塊,你會清晰的看到顏色區塊井井有理,都是一塊一塊的,折射的是整潔的代碼,咱們須要修改哪一個功能,就直接在哪塊代碼修改便可。
這就是 Composition API,在組件間的邏輯須要複用的時候,在組件內代碼須要剝離的時候,咱們放心大膽的用!
經過對 Composition API 的瞭解,你會發如今代碼組織上有一個很大的變化:幹掉了 Vue2.x 中神奇的 this。
在 Vue2.x 中,咱們的代碼中大量的使用到了 this,組件中的 props, data,methods 都是綁定到 this 上下文,而後由 this 去訪問。
那麼使用 Compositon API 以後,當涉及到跨組件之間提取、複用邏輯時,就會很是的靈活。一個合成函數只依賴於它的參數和全局引入的 Vue APIs,而不是充滿魔法的 this 上下文。咱們只須要將組件中你想複用的那部分代碼抽離,而後將它導出爲函數就能夠了。
好比上面中的 listenMouse.js,單獨導出 useMouse,在其餘組件均可以使用。
然而事情可能都有兩面性~
最近看到有人用 Composition API 實踐應用,功能不大,在閱讀完以後,筆者認爲在 Vue3.0 的 Composition API 中未來會避免不了出現 「麪條代碼」 這個問題!
麪條代碼:代碼的控制結構複雜、混亂,邏輯不清,關係耦合,讓人一時難以理解。
麪條代碼的形象例子:
這圖讓人看了一臉懵逼,如贊成大利麪條同樣,所有混在一塊兒,一時難以確切找到調用出入口和代碼之間的關係是如何的。
Options API 和 Composition API 的差別咱們上面已經分析過了,咱們再換個角度總結一下:
Options API 約定:
你會發現 Options APi 都約定了咱們該在哪一個位置作什麼事,這反倒在必定程度上也強制咱們進行了代碼分割。
如今用 Composition API,再也不這麼約定了,因而乎,代碼組織很是靈活,咱們的控制代碼寫在 setup 裏面便可。
若是做爲一個新手,或者不鄭重思考的碼農,那麼在邏輯愈來愈複雜的狀況下,setup 代碼量愈來愈多,一樣 setup 裏面的 return 愈來愈複雜,勢必會落入「麪條代碼」的斡旋之中。
就以我上面提到的,我看完的 Composition API 的實踐爲例,該應用不大,可是一個 setup 方法整整 350 行代碼了……
咱們沒有了 this 上下文,沒有了 Options API 的強制代碼分離。Composition API 給了咱們更加廣闊的天地,那麼咱們更加須要慎重自約起來。
對於複雜的邏輯代碼,咱們要更加劇視起 Composition API 的初心,不要吝嗇使用 Composition API 來分離代碼,用來切割成各類模塊導出。
咱們指望是這樣的:
import useA from './a';
import useB from './b';
import useC from './c';
export default { setup (props) { let { a, methodsA } = useA(); let { b, methodsB } = useA(); let { c, methodsC } = useC(); return { a, methodsA, b, methodsB, c, methodsC } } } 複製代碼
就算 setup 內容代碼量愈來愈大,可是始終圍繞着大而不亂,代碼結構清晰的路子前進。
setup 是咱們的代碼控制器,儘可能不要寫入大量的業務邏輯代碼。始終秉承着爲 「控制器分憂,爲 setup 減負」 的思想來擼代碼!
固然咱們一樣要規避墜入「混沌代碼」的魔咒。還需秉承:高內聚,低耦合 的擼代碼方針。
讓咱們一塊兒靜待 Vue3.0 正式版的到來!
歡迎關注個人微信公衆號,一塊兒作靠譜前端!