[Vue]淺談Vue3組合式API帶來的好處以及選項API的壞處

shiramashiro發表於2021-11-16

前言

如果是經驗不夠多的同志在學習Vue的時候,在最開始會接觸到Vue傳統的方式(選項式API),後邊會接觸到Vue3的新方式 —— 組合式API。相信會有不少同志會陷入迷茫,因為我第一次聽到新的名詞時也陷入了困擾,所以,到底什麼是組合式API呢?

選項式API的壞處

程式碼碎片化

通常在維護和開發一個元件時,分為 data、methods、computed、props 等。假如有一些業務在選項 API 的 data、methods、computed 中進行操作。把要關注的相同視角分別用不同顏色的框子框起來,發現我們的關注點被拆分成了這樣:

[Vue]淺談Vue3組合式API帶來的好處以及選項API的壞處

先不說大元件的關注點會被拆分成怎麼樣,就單純這一個很簡單的演示就能夠讓各位同志體會到選項式 API 的壞處了。當我們的元件開始變得更大時,邏輯關注點的列表也會增長。如果你是一個軍隊的指揮官,你會選擇把戰線拉得很長嗎?費時費力,後勤補給也跟不上。

這種碎片化使得理解和維護複雜元件變得困難,選項的分離掩蓋了潛在的邏輯問題。此外,在處理單個邏輯關注點時,我們必須不斷地“跳轉”相關程式碼的選項塊。

邏輯不復用

上一小節中說到選項式API使程式碼變得碎片化,曾經我想過把一段多次使用到的業務程式碼抽離到一個單獨的 js 檔案裡。我也遇到過一些困擾的小問題,導致我不能完成理想。

首先,在 data 選項宣告的變數才是響應式資料。其次,在 methods 選項宣告的函式才可以操控元件裡的響應式資料。這是下文分析選項式API邏輯不復用時的重要前提條件。

在 demo.js 檔案裡,我定義了一個 a 變數,calc 函式改變 a 的值:

export let a = 'foo'
export function calc() { a = a + 'bar' }

對於這樣的抽離方式,在使用的時候,依舊是需要把變數匯入到 data 選項,使其成為響應式資料;函式匯入到 methods 選項。

import { a, calc } from './demo.js'
export default {
    data() { return { a } },
    methods: { _calc() { calc() } }
}

由於 demo.js 檔案裡的函式操作的是 demo.js 檔案裡的變數 a ,而不是元件中響應式資料 a。導致我點選了按鈕之後頁面未作出任何反應。

解決方法是,calc 函式接受一個形參,然後再返回。當然可以!這只是一個簡單的字元拼接而已。但是,這不是非常直接的辦法,要經歷一些曲折,同樣會導致程式碼難讀懂的問題。

官方提供的解決方案是混入,而混入還是在寫選項API。不再選項API!不再選項API!不再選項API!,因為不符合期望。讀到這裡,想必知道了選項式API的壞處了。

一句話總結選項式API的壞處就是:程式碼碎片化、邏輯不復用

組合式API的好處

程式碼集中化

為什麼組合式API就可以讓程式碼不碎片化呢?因為組合式API的組合就在於它把變數、函式集中在一起,減少分離掩蓋的潛在的邏輯問題,不在“跳轉”相關程式碼的選項塊。

所以,是如何集中化的呢?因為 Vue3 要實現程式碼集中化,所以,Vue3 的許多選項都抽離成為了一個個模組(這是我的猜想,因為每次用到什麼必須從 vue 模組匯入什麼)。

組合式API就是一個 setup 函式,我們的所有程式碼全部都要寫在這裡面。

import { ref } from 'vue'
export default {
	setup() {
        let a = ref('foo')
        function calcA() { a.value = a.value + 'bar' }
        let b = ref('bar')
        function calcB() { b.value = b.value + 'foo' }
        let c = ref('hello')
        function calcC() { c.value = c.value + 'world' }
        let d = ref('world')
       	function calcD() { d.value = d.value + 'hello' }
	}
}

現在,我們的關注點會被集中化,用圖表示就是:

[Vue]淺談Vue3組合式API帶來的好處以及選項API的壞處

不知道各位同志是否有感受到這種變化,筆者已經感受到組合式API的強大了。

邏輯高複用

還記得第一章第二小節說到的問題嗎?Vue3 的許多選項都抽離成為了一個個模組,所以我們可以在一個單獨的 js 宣告響應式資料了,就是利用ref函式來操作的。

我們新建一個 demo2.js 檔案,首先引入 vue 模組中的 ref 函式,用於宣告一個響應式資料:

import { ref } from 'vue'
export let a = ref('foo')
export function calc() { a.value = a.value + 'bar' }

然後我們在其他元件中使用:

import { a, calc } from './demo2.js'
export default {
    setup() {
        return { a, calc } // 這裡需要匯出a和calc
    }
}

由於在 demo2.js 的 calc 函式操作的已經是一個響應式資料了,所以,元件一旦用到了這個模組中的東西,它都會反映到頁面中。

大功告成,這得益於 Vue3 的一大進步啊!現在我們寫程式碼可以寫得非常舒服了。再加上 Vue3 是 TS 重構的,按道理來說是非常支援 TS 的寫法的,前提是你的專案支援 TS。請問各位同志,Vue3 是不是可以適合開發大型應用了呢?

總結

將同一個邏輯關注點相關程式碼收集在一起,在處理單個邏輯關注點時,我們必須不斷地“跳轉”相關程式碼的選項塊。使得開發人員更容易閱讀和理解這些程式碼,這正是組合式 API 要解決的問題。

組合式 API 也導致以往的寫法不相同,所以各位同志還是需要花時間去適應一段時間。

相關文章