無法適應Vue 3組合式API?進來看看

藍瘦,想哭

我最近在死磕Vue 3的組合式API,說實話,雖然道理都懂,但寫起來卻非常難受。

藍瘦主要表現有這么幾點:

一、代碼不像Vue 2那樣被約束,寫起來心累怎么辦

尤雨溪觀點:

首先說尤雨溪完全清楚這個問題,也承認有這個問題,選項式API有天然的代碼約束,而組合式API沒有天然的代碼約束,但是他依然認為組合式API才是未來,尤雨溪支持組合式API的主要理由是,在大型的應用開發里,邏輯只有和用到的數據放在一起才更容易維護,這叫做“關注點分離”,這樣可以提升可維護性,可維護性大于一切,而且不再有反復橫跳現象。

我的觀點:

我的觀點絕對代表了一大批人的意見,我認為,這兩種模式各有利弊,既然都說組合式API是未來,那么我主要說說組合式API的弊端。

  1. 關于大型應用

如果大型應用的一個文件有幾千行代碼,那么你為什么不早早地分拆組件、拆分hook呢?在文件代碼行數較少的前提下,我認為組合式API的優勢并不明顯。

  1. 關于反復橫跳

反復橫跳確實存在,我認為橫跳是一定會有的,誰找代碼不是滾動滾輪到處找?選項式API是大橫跳,組合式API是小橫跳,都要跳。選項式API是滾動距離長,組合式API是滾動距離短,但是滾動距離長不代表用時長,畢竟滾動時間+人腦反應時間才是全部時間,選項式API的人腦反應時間并不長,有時還更短。只要你對代碼區塊位置形成固化記憶,并且用心給變量命名,這都不是問題。

對于代碼區塊位置形成固化記憶這個事,選項式API其實是有優勢的,就是說,選項式API最大的特點就是“選項”,你可以把“選項”視為索引,根據索引去找代碼,在遵循官方編寫建議的前提下,你腦中已經明白,computed屬性一定寫在data屬性的下方,watch屬性又在computed屬性的下方,methods屬性又在watch屬性的下方,生命周期夾在watch和methods之間,這些都相當于第一級分支,它們的屬性是第二級分支。你對你要找的代碼的大概位置很清楚。樹狀結構的終端就是各個變量,computed下面的終端變量一定是計算屬性,一定確定以及肯定,無心智負擔。

組合式API就不容易分這么細,畢竟它沒有第一級分支的約束,比如你在2個data之間夾一個computed是完全可以的,這時你為了減少找代碼的心智負擔,你就總要整理各個變量的書寫順序,結果,就又成了選項式API的組織形式。另外,組合式API的最左側只能看到一個個的let和const,然后你會看到變量名,從變量名,你無法一眼看出它是data還是computed,所以你的視線只能繼續右移,看變量名后面的代碼有沒有computed字樣,而選項式API,早在選第一級分支的時候我就看過了computed,它下面的一定是計算屬性,毫無疑問。

對于用心給變量命名這個事,我意思是,請你讓自己遵循比較嚴苛的命名法則,比如英文單詞的單復數要敏感,事件函數寫成onChangeXXonClickOO的格式,例如我給<select>元素寫事件,我肯定是寫onChangeXX,我并不需要橫跳確認。在遵守足夠規則的前提下,你完全可以憑簡單記憶就寫出變量名和方法名,并不需要橫跳去查變量名。

  1. 關于選項式API的無盡的this

組合式API一出,一些人驚呼,終于擺脫無盡的this了!

我拜托,this這個關鍵字,從誕生以來就是為了簡便開發,也不是JS獨有,如果覺得this是“壞的”,倒不如說“編程語言都是垃圾”算了。

在選項式API里,我們只需要使用箭頭函數,保證this始終指向Vue組件實例就好了,組件內數據方法皆在this下,我不知道這有什么不好。我不想多解釋了。

  1. 關于組合式API的hook解決了選項式API的mixins的痛點

這話確實沒錯,如果你的主組件需要分拆,mixins又多、又需要通信,那么,至少這個主組件是強烈推薦使用組合式API,哪怕你并不喜歡組合式API。

二、組合式API代碼混亂怎么辦

目前我的解決方案是使用2種范式。

范式一:采用hook

利用hook,你可以將全體代碼拆分為若干個邏輯關注點,每個關注點寫成一個hook,然后你可以有2種方式存放hook:

  • 第一種方式,在主文件里拆分成幾個hook函數。
  • 第二種方式,主文件旁邊建立若干個hook文件。

這時候,原本要return 20個變量,現在大約是拆成了3個hook,每個hook里return 7個變量,主文件會return 3個變量,這樣可維護性更高。

范式二:主體用選項式API,setup()只引入和return hook,不處理邏輯

這是范式一的升級,是我目前采用的范式,至少2021年內我會始終采用這種范式,這種范式的優勢是,避免Mixins的缺陷,也避免組合式API代碼需要刻意維護代碼區塊的問題。

舉個例子,先編一個hook文件:

import { ref } from "@vue/reactivity";

function hook1 () {
  let a = ref(false);
  function changeA() {
    a.value = !a.value;
  }
  return {a, changeA}
}

export default hook1;

主文件按照選項式API編寫,setup()只負責返回hook,其他沿用Vue 2的編寫方式:

import Hook1 from "../hooks/hook1";

export default {
  setup() {
    let useHook1 = Hook1();
    let useHook1Other = Hook1();
    return { useHook1, useHook1Other };
  },
  mounted() {
    this.useHook1.changeA();
    console.log(this.useHook1.a.value); // true
    this.useHook1Other.changeA();
    console.log(this.useHook1Other.a.value); // true
  },
};

同時,<template>里的變量由于有useHook1.、useHook1Other.前綴,也就形成了模塊化。

三、定義一個響應式變量的時候,總會忘記引入vue方法怎么辦

解決辦法是,當你寫完let a = ref,雖然ref只有3個字母,并不需要聯想輸入,但你此時依然應該敲一下Tab鍵,vetur插件會幫你創建import { ref } from 'vue'reactive等同理。你并不需要提前寫import { } from 'vue'

四、總忘記在return里添加變量怎么辦

并沒有什么快捷方法讓return {}中自動出現a,,只能手寫。

五、return的變量太多,密密麻麻怎么辦

確實,選項式API并不需要任何return,而且變量存放在各個分支(data、computed等)上,但是組合式API就需要return,而且是所有模板用得到的變量都需要return,導致data、computed、method全混在一起。

解決辦法是:

  1. 可以使用hook,使用之后,每個return的變量個數呈幾何級減少,這是比較好的解決辦法。

  2. 另外,可以使用<script setup>,免去return,但是你要放棄選項式API。

六、總是忘記寫ref對象的.value怎么辦

可以使用<script setup>和ref:標簽,但是你要放棄選項式API。

七、使用<script setup>時總忘記用ref:標簽怎么辦

那沒辦法,習慣就好??傊?,.valueref:你總要選擇一樣,看你的個人習慣吧。

八、解構導致失去響應式怎么辦

用toRefs。

const {a,b,c} = toRefs(Proxy對象)

解決辦法倒是簡單,主要是要形成肌肉記憶,不要忘記。

九、對引用類型數據不知道用ref還是用reactive怎么辦

如果后續打算重賦值變量,還不丟失響應式,那么用ref,如果后續只修改屬性,那么用reactive。不確定未來會怎樣的,先用reactive,未來再改。

總結:到底應不應該用組合式API,以什么原則定

  1. 盡管組合式API更適合大型項目,但是你不要等到大型項目才開始接觸Vue 3,那時候你真的會欲仙欲死,我建議你現在就開始學組合式API。

  2. 你的第一個Vue 3上線項目應該使用選項式API,這樣風險最低。之后可以將代碼逐步重構成組合式API。在這個過程中,你就會有感悟,到底是組合式API還是選項式API更好?其實你可以根據每個組件的特點來定。

  3. 拆分、復用是一門學問,要仔細體會。

  4. 不要一味否認另一套API,就像我有時候也用函數式組件,也偶爾用JSX,該用就用。我建議你主打其中一種,副打另一種,不要一味只使用一種,在一個項目內出現兩種API寫法是正常的做法,在一個組件里出現兩種寫法也沒問題,都是我推薦的做法。

  5. 選項式API有它某些不可比擬的優勢,尤雨溪不至于傻到幾個版本之后徹底取消選項式API,所以,如果你打算主打選項式API,副打組合式API,有時候還混用,我認為沒問題,就算幾個大版本之后,選項式API消失了,也依然會有高手寫出一個選項式API插件讓你用,放心吧。如果到時候真的沒有這種插件,說明選項式API確實是過時了,那時候相信你也早已習慣了組合式API,并且組合式API那時候已經有了更好的開發范式。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容