Vue3 究竟好在哪裏?(和 React Hook 的詳細對比)

前言

這幾天 Vue 3.0 Beta 版本發佈了,本覺得是皆大歡喜的一件事情,可是論壇裏仍是看到了不少反對的聲音。主流的反對論點大概有以下幾點:html

  1. 意大利麪代碼結構吐槽:
「太失望了。雜七雜八一堆丟在 setup 裏,我還不如直接用 react」

個人天,3.0 這麼搞的話,代碼結構不清晰,語義不明確,無異於把 vue 自身優勢都扔了前端

怎麼感受代碼結構上沒有 2.0 清晰了呢 😂 這要是代碼量上去了是否是很差維護啊vue

  1. 抄襲 React 吐槽:
抄來抄去沒本身的個性

有 react 香嗎?愈來愈像 react 了react

在我看來,Vue 黑暗的一天還遠遠沒有過去,不少人其實並無認真的去看 Vue-Composition-Api 文檔中的 動機 章節,本文就以這個章節爲線索,從 代碼結構底層原理 等方面來一一打消你們的一些顧慮。ios

在文章的開頭,首先要標明一下做者的立場,我對於 React 和 Vue 都很是的喜歡。他們都有着各自的優缺點,本文絕無引戰之意。兩個框架都很棒!只是各有優缺點而已。React 的 Immutable 其實也帶來了不少益處,而且 Hook 的思路仍是 Facebook 團隊的大佬們獨創的,真的是很讓人讚歎的設計,我對 React 100% 致敬!git

設計動機

大如 Vue3 這種全球熱門的框架,任何一個 breaking-change 的設計必定有它的深思熟慮和權衡,那麼 composition-api 出現是爲了解決什麼問題呢?這是一個咱們須要首先思考明白的問題。程序員

首先拋出 Vue2 的代碼模式下存在的幾個問題。github

  1. 隨着功能的增加,複雜組件的代碼變得愈來愈難以維護。 尤爲發生你去新接手別人的代碼時。 根本緣由是 Vue 的現有 API 經過「選項」組織代碼,可是在大部分狀況下,經過邏輯考慮來組織代碼更有意義。
  2. 缺乏一種比較「乾淨」的在多個組件之間提取和複用邏輯的機制。
  3. 類型推斷不夠友好。

邏輯重用

相信不少接觸過 React Hook 的小夥伴已經對這種模式下組件間邏輯複用的簡單性有了必定的認知,自從 React 16.7 發佈以來,社區涌現出了海量的 Hook 輪子,以及主流的生態庫 react-routerreact-redux 等等所有擁抱 Hook,均可以看出社區的同好們對於 Hook 開發機制的贊同。面試

其實組件邏輯複用在 React 中是經歷了很長的一段發展歷程的,
mixin -> HOC & render-props -> Hookmixin 是 React 中最先啓用的一種邏輯複用方式,由於它的缺點實在是多到數不清,然後面的兩種也有着本身的問題,好比增長組件嵌套啊、props 來源不明確啊等等。能夠說到目前爲止,Hook 是相對完美的一種方案。vue-router

固然,個人一向風格就是上代碼對比,我就拿 HOC 來講吧,Github 上的一個真實的開源項目裏就出現了這樣的場景:

HOC 對比 Hook

class MenuBar extends React.Component {
  // props 裏混合着來自各個HOC傳入的屬性,還有父組件傳入的屬性。
  handleClickNew() {
    const readyToReplaceProject = this.props.confirmReadyToReplaceProject(
      this.props.intl.formatMessage(sharedMessages.replaceProjectWarning)
    );
    this.props.onRequestCloseFile();
    if (readyToReplaceProject) {
      this.props.onClickNew(this.props.canSave && this.props.canCreateNew);
    }
    this.props.onRequestCloseFile();
  }
  handleClickRemix() {
    this.props.onClickRemix();
    this.props.onRequestCloseFile();
  }
  handleClickSave() {
    this.props.onClickSave();
    this.props.onRequestCloseFile();
  }
  handleClickSaveAsCopy() {
    this.props.onClickSaveAsCopy();
    this.props.onRequestCloseFile();
  }
}

export default compose(
  // 國際化
  injectIntl,
  // 菜單
  MenuBarHOC,
  // react-redux
  connect(mapStateToProps, mapDispatchToProps)
)(MenuBar);

沒錯,這裏用 compose 函數組合了好幾個 HOC,其中還有 connect 這種 接受幾個參數返回一個接受組件做爲函數的函數 這種東西,若是你是新上手(或者哪怕是 React 老手)這套東西的人,你會在 「這個 props 是從哪一個 HOC 裏來的?」,「這個 props 是外部傳入的仍是 HOC 裏獲得的?」這些問題中迷失了大腦,最終走向墮落(誤)。

不談 HOC,個人腦子已經快炸開來了,來看看用 Hook 的方式複用邏輯是怎麼樣的場景吧?

function MenuBar(props) {
  // props 裏只包含父組件傳入的屬性
  const { show } = props;
  // 菜單
  const { onClickRemix, onClickNew } = useMenuBar();
  // 國際化
  const { intl } = useIntl();
  // react-redux
  const { user } = useSelector((store) => store.user);
}

export default MenuBar;

一切都變得很明朗,我能夠很是清楚的知道這個方法的來源,intl 是哪裏注入進來的,點擊了 useMenuBar 後,就自動跳轉到對應的邏輯,維護和可讀性都極大的提升了。

固然,這是一個比較「刻意」的例子,可是相信我,我在 React 開發中已經體驗過這種收益了。隨着組件的「職責」愈來愈多,只要你掌握了這種代碼組織的思路,那麼你的組件並不會膨脹到不可讀。

常見的請求場景

再舉個很是常見的請求場景。

在 Vue2 中若是我須要請求一份數據,而且在loadingerror時都展現對應的視圖,通常來講,咱們會這樣寫:

<template>
    <div v-if="error">failed to load</div>
    <div v-else-if="loading">loading...</div>
    <div v-else>hello {{fullName}}!</div>
</template>

<script>
import { createComponent, computed } from 'vue'

export default {
  data() {
    // 集中式的data定義 若是有其餘邏輯相關的數據就很容易混亂
    return {
        data: {
            firstName: '',
            lastName: ''
        },
        loading: false,
        error: false,
    },
  },
  async created() {
      try {
        // 管理loading
        this.loading = true
        // 取數據
        const data = await this.$axios('/api/user')
        this.data = data
      } catch (e) {
        // 管理error
        this.error = true
      } finally {
        // 管理loading
        this.loading = false
      }
  },
  computed() {
      // 沒人知道這個fullName和哪一部分的異步請求有關 和哪一部分的data有關 除非仔細閱讀
      // 在組件大了之後更是如此
      fullName() {
          return this.data.firstName + this.data.lastName
      }
  }
}
</script>

這段代碼,怎麼樣都談不上優雅,湊合的把功能完成而已,而且對於loadingerror等處理的可複用性爲零。

數據和邏輯也被分散在了各個option中,這還只是一個邏輯,若是又多了一些邏輯,多了datacomputedmethods?若是你是一個新接手這個文件的人,你如何迅速的分辨清楚這個method是和某兩個data中的字段關聯起來的?

讓咱們把zeit/swr的邏輯照搬到 Vue3 中,

看一下swr在 Vue3 中的表現:

<template>
    <div v-if="error">failed to load</div>
    <div v-else-if="loading">loading...</div>
    <div v-else>hello {{fullName}}!</div>
</template>

<script>
import { createComponent, computed } from 'vue'
import useSWR from 'vue-swr'

export default createComponent({
  setup() {
      // useSWR幫你管理好了取數、緩存、甚至標籤頁聚焦從新請求、甚至Suspense...
      const { data, loading, error } = useSWR('/api/user', fetcher)
      // 輕鬆的定義計算屬性
      const fullName = computed(() => data.firstName + data.lastName)
      return { data, fullName, loading, error }
  }
})
</script>

就是這麼簡單,對嗎?邏輯更加聚合了。

對了,順嘴一提, use-swr 的威力可遠遠不止看到的這麼簡單,隨便舉幾個它的能力:

  1. 間隔輪詢
  2. 請求重複數據刪除
  3. 對於同一個 key 的數據進行緩存
  4. 對數據進行樂觀更新
  5. 在標籤頁聚焦的時候從新發起請求
  6. 分頁支持
  7. 完備的 TypeScript 支持

等等等等……而這麼多如此強大的能力,都在一個小小的 useSWR() 函數中,誰能說這不是魔法呢?

相似的例子還數不勝數。

umi-hooks

react-use

代碼組織

上面說了那麼多,還只是說了 Hook 的其中一個優點。這其實並不能解決「意大利麪條代碼」的問題。當邏輯多起來之後,組件的邏輯會糅合在一塊兒變得一團亂麻嗎?

從獲取鼠標位置的需求講起

咱們有這樣一個跨組件的需求,我想在組件裏得到一個響應式的變量,能實時的指向我鼠標所在的位置。

Vue 官方給出的自定義 Hook 的例子是這樣的:

import { ref, onMounted, onUnmounted } from "vue";

export function useMousePosition() {
  const x = ref(0);
  const y = ref(0);

  function update(e) {
    x.value = e.pageX;
    y.value = e.pageY;
  }

  onMounted(() => {
    window.addEventListener("mousemove", update);
  });

  onUnmounted(() => {
    window.removeEventListener("mousemove", update);
  });

  return { x, y };
}

在組件中使用:

import { useMousePosition } from "./mouse";

export default {
  setup() {
    const { x, y } = useMousePosition();
    // other logic...
    return { x, y };
  },
};

就這麼簡單,無需多言。在任何組件中咱們須要「獲取響應式的鼠標位置」,而且和咱們的「視圖層」關聯起來的時候,僅僅須要簡單的一句話便可。而且這裏返回的 xy 是由 ref 加工過的響應式變量,咱們能夠用 watch 監聽它們,能夠把它們傳遞給其餘的自定義 Hook 繼續使用。幾乎能作到你想要的一切,只須要發揮你的想象力。

從 Vue 官方的例子講起

上面的例子足夠入門和精簡,讓咱們來到現實世界。舉一個 Vue CLI UI file explorer 官方吐槽的例子,這個組件是 Vue-CLI 的 gui 中(也就是日常咱們命令行裏輸入 vue ui 出來的那個圖形化控制檯)的一個複雜的文件瀏覽器組件,這是 Vue 官方團隊的大佬寫的,相信是比較有說服力的一個案例了。

這個組件有如下的幾個功能:

  1. 跟蹤當前文件夾狀態並顯示其內容
  2. 處理文件夾導航(打開,關閉,刷新...)
  3. 處理新文件夾的建立
  4. 切換顯示收藏夾
  5. 切換顯示隱藏文件夾
  6. 處理當前工做目錄更改

文檔中提出了一個尖銳的靈魂之問,你做爲一個新接手的開發人員,可以在茫茫的 methoddatacomputed 等選項中一目瞭然的發現這個變量是屬於哪一個功能嗎?好比「建立新文件夾」功能使用了兩個數據屬性,一個計算屬性和一個方法,其中該方法在距數據屬性「一百行以上」的位置定義。

當一個組價中,維護同一個邏輯須要跨越上百行的「空間距離」的時候,即便是讓我去維護 Vue 官方團隊的代碼,我也會暗搓搓的吐槽一句,「這寫的什麼玩意,這變量幹嗎用的!」

尤大很貼心的給出了一張圖,在這張圖中,不一樣的色塊表明着不一樣的功能點。

其實已經作的不錯了,可是在維護起來的時候仍是挺災難的,好比淡藍色的那個色塊表明的功能。我想要完整的理清楚它的邏輯,須要「上下反覆橫跳」,相似的事情我已經經歷過好屢次了。

而使用 Hook 之後呢?咱們能夠把「新建文件夾」這個功能美美的抽到一個函數中去:

function useCreateFolder(openFolder) {
  // originally data properties
  const showNewFolder = ref(false);
  const newFolderName = ref("");

  // originally computed property
  const newFolderValid = computed(() => isValidMultiName(newFolderName.value));

  // originally a method
  async function createFolder() {
    if (!newFolderValid.value) return;
    const result = await mutate({
      mutation: FOLDER_CREATE,
      variables: {
        name: newFolderName.value,
      },
    });
    openFolder(result.data.folderCreate.path);
    newFolderName.value = "";
    showNewFolder.value = false;
  }

  return {
    showNewFolder,
    newFolderName,
    newFolderValid,
    createFolder,
  };
}

咱們約定這些「自定義 Hook」以 use 做爲前綴,和普通的函數加以區分。

右邊用了 Hook 之後的代碼組織色塊:

咱們想要維護紫色部分功能的邏輯,那就在紫色的部分去找就行了,反正不會有其餘「色塊」裏的變量或者方法影響到它,很快咱就改好了需求,6 點準時下班!

這是 Hook 模式下的組件概覽,真的是一目瞭然。感受我也能夠去維護 @vue/ui 了呢(假的)。

export default {
  setup() {
    // ...
  },
};

function useCurrentFolderData(networkState) {
  // ...
}

function useFolderNavigation({ networkState, currentFolderData }) {
  // ...
}

function useFavoriteFolder(currentFolderData) {
  // ...
}

function useHiddenFolders() {
  // ...
}

function useCreateFolder(openFolder) {
  // ...
}

再來看看被吐槽成「意大利麪條代碼」的 setup 函數。

export default {
  setup() {
    // Network
    const { networkState } = useNetworkState();

    // Folder
    const { folders, currentFolderData } = useCurrentFolderData(networkState);
    const folderNavigation = useFolderNavigation({ networkState, currentFolderData });
    const { favoriteFolders, toggleFavorite } = useFavoriteFolders(currentFolderData);
    const { showHiddenFolders } = useHiddenFolders();
    const createFolder = useCreateFolder(folderNavigation.openFolder);

    // Current working directory
    resetCwdOnLeave();
    const { updateOnCwdChanged } = useCwdUtils();

    // Utils
    const { slicePath } = usePathUtils();

    return {
      networkState,
      folders,
      currentFolderData,
      folderNavigation,
      favoriteFolders,
      toggleFavorite,
      showHiddenFolders,
      createFolder,
      updateOnCwdChanged,
      slicePath,
    };
  },
};

這是誰家的小仙女這麼美啊!這邏輯也太清晰明瞭,和意大利麪沒半毛錢關係啊!

對比

Hook 和 Mixin & HOC 對比

說到這裏,仍是不得不把官方對於「Mixin & HOC 模式」所帶來的缺點整理一下。

  1. 渲染上下文中公開的屬性的來源不清楚。 例如,當使用多個 mixin 讀取組件的模板時,可能很難肯定從哪一個 mixin 注入了特定的屬性。
  2. 命名空間衝突。 Mixins 可能會在屬性和方法名稱上發生衝突,而 HOC 可能會在預期的 prop 名稱上發生衝突。
  3. 性能問題,HOC 和無渲染組件須要額外的有狀態組件實例,這會下降性能。

而 「Hook」模式帶來的好處則是:

  1. 暴露給模板的屬性具備明確的來源,由於它們是從 Hook 函數返回的值。
  2. Hook 函數返回的值能夠任意命名,所以不會發生名稱空間衝突。
  3. 沒有建立僅用於邏輯重用的沒必要要的組件實例。

固然,這種模式也存在一些缺點,好比 ref 帶來的心智負擔,詳見drawbacks

React Hook 和 Vue Hook 對比

其實 React Hook 的限制很是多,好比官方文檔中就專門有一個章節介紹它的限制:

  1. 不要在循環,條件或嵌套函數中調用 Hook
  2. 確保老是在你的 React 函數的最頂層調用他們。
  3. 遵照這條規則,你就能確保 Hook 在每一次渲染中都按照一樣的順序被調用。這讓 React 可以在屢次的 useState 和 useEffect 調用之間保持 hook 狀態的正確。

而 Vue 帶來的不一樣在於:

  1. 與 React Hooks 相同級別的邏輯組合功能,但有一些重要的區別。 與 React Hook 不一樣,setup 函數僅被調用一次,這在性能上比較佔優。
  2. 對調用順序沒什麼要求,每次渲染中不會反覆調用 Hook 函數,產生的的 GC 壓力較小。
  3. 沒必要考慮幾乎老是須要 useCallback 的問題,以防止傳遞函數prop給子組件的引用變化,致使無必要的從新渲染。
  4. React Hook 有臭名昭著的閉包陷阱問題(甚至成了一道熱門面試題,omg),若是用戶忘記傳遞正確的依賴項數組,useEffect 和 useMemo 可能會捕獲過期的變量,這不受此問題的影響。 Vue 的自動依賴關係跟蹤確保觀察者和計算值始終正確無誤。
  5. 不得不提一句,React Hook 裏的「依賴」是須要你去手動聲明的,並且官方提供了一個 eslint 插件,這個插件雖然大部分時候挺有用的,可是有時候也特別煩人,須要你手動加一行醜陋的註釋去關閉它。

咱們承認 React Hooks 的創造力,這也是 Vue-Composition-Api 的主要靈感來源。上面提到的問題確實存在於 React Hook 的設計中,咱們注意到 Vue 的響應式模型剛好完美的解決了這些問題。

順嘴一題,React Hook 的心智負擔是真的很嚴重,若是對此感興趣的話,請參考:

使用 react hooks 帶來的收益抵得過使用它的成本嗎? - 李元秋的回答 - 知乎
https://www.zhihu.com/questio...

而且我本身在實際開發中,也遇到了不少問題,尤爲是在我想對組件用 memo 進行一些性能優化的時候,閉包的問題爆炸式的暴露了出來。最後我用 useReducer 大法解決了其中不少問題,讓我不得不懷疑這從頭至尾會不會就是 Dan 的陰謀……(別想逃過 reducer

React Hook + TS 購物車實戰(性能優化、閉包陷阱、自定義 hook)

原理

既然有對比,那就從原理的角度來談一談二者的區別,

在 Vue 中,之因此 setup 函數只執行一次,後續對於數據的更新也能夠驅動視圖更新,歸根結底在於它的「響應式機制」,好比咱們定義了這樣一個響應式的屬性:

Vue

<template>
  <div>
    <span>{{count}}</span>
    <button @click="add"> +1 </button>
  </div>
</template>

export default {
    setup() {
        const count = ref(0)

        const add = () => count.value++

        return { count, add }
    }
}

這裏雖然只執行了一次 setup 可是 count 在原理上是個 「響應式對象」,對於其上 value 屬性的改動,

是會觸發「由 template 編譯而成的 render 函數」 的從新執行的。

若是須要在 count 發生變化的時候作某件事,咱們只須要引入 effect 函數:

<template>
  <div>
    <span>{{count}}</span>
    <button @click="add"> +1 </button>
  </div>
</template>

export default {
    setup() {
        const count = ref(0)

        const add = () => count.value++

        effect(function log(){
            console.log('count changed!', count.value)
        })

        return { count, add }
    }
}

這個 log 函數只會產生一次,這個函數在讀取 count.value 的時候會收集它做爲依賴,那麼下次 count.value 更新後,天然而然的就能觸發 log 函數從新執行了。

仔細思考一下這之間的數據關係,相信你很快就能夠理解爲何它能夠只執行一次,可是卻威力無窮。

實際上 Vue3 的 Hook 只須要一個「初始化」的過程,也就是 setup,命名很準確。它的關鍵字就是「只執行一次」。

React

一樣的邏輯在 React 中,則是這樣的寫法:

export default function Counter() {
  const [count, setCount] = useState(0);

  const add = () => setCount((prev) => prev + 1);

  // 下文講解用
  const [count2, setCount2] = useState(0);

  return (
    <div>
      <span>{count}</span>
      <button onClick={add}> +1 </button>
    </div>
  );
}

它是一個函數,而父組件引入它是經過 <Counter /> 這種方式引入的,實際上它會被編譯成 React.createElement(Counter) 這樣的函數執行,也就是說每次渲染,這個函數都會被完整的執行一次。

useState 返回的 countsetCount 則會被保存在組件對應的 Fiber 節點上,每一個 React 函數每次執行 Hook 的順序必須是相同的,舉例來講。 這個例子裏的 useState 在初次執行的時候,因爲執行了兩次 useState,會在 Fiber 上保存一個 { value, setValue } -> { value2, setValue2 } 這樣的鏈表結構。

而下一次渲染又會執行 count 的 useStatecount2 的 useState,那麼 React 如何從 Fiber 節點上找出上次渲染保留下來的值呢?固然是隻能按順序找啦。

第一次執行的 useState 就拿到第一個 { value, setValue },第二個執行的就拿到第二個 { value2, setValue2 }

這也就是爲何 React 嚴格限制 Hook 的執行順序和禁止條件調用。

假如第一次渲染執行兩次 useState,而第二次渲染時第一個 useState 被 if 條件判斷給取消掉了,那麼第二個 count2 的 useState 就會拿到鏈表中第一條的值,徹底混亂了。

若是在 React 中,要監聽 count 的變化作某些事的話,會用到 useEffect 的話,那麼下次 render

以後會把先後兩次 render 中拿到的 useEffect 的第二個參數 deps 依賴值進行一個逐項的淺對比(對先後每一項依次調用 Object.is),好比

export default function Counter() {
  const [count, setCount] = useState(0);

  const add = () => setCount((prev) => prev + 1);

  useEffect(() => {
    console.log("count updated!", count);
  }, [count]);

  return (
    <div>
      <span>{count}</span>
      <button onClick={add}> +1 </button>
    </div>
  );
}

那麼,當 React 在渲染後發現 count 發生了變化,會執行 useEffect 中的回調函數。(細心的你能夠觀察出來,每次渲染都會從新產生一個函數引用,也就是 useEffect 的第一個參數)。

是的,React 仍是不可避免的引入了 依賴 這個概念,可是這個 依賴 是須要咱們去手動書寫的,實時上 React 社區所討論的「心智負擔」也基本上是因爲這個 依賴 所引發的……

因爲每次渲染都會不斷的執行併產生閉包,那麼從性能上和 GC 壓力上都會稍遜於 Vue3。它的關鍵字是「每次渲染都從新執行」。

關於抄襲 React Hook

其實前端開源界談抄襲也不太好,一種新的模式的出現的值得框架之間相互借鑑和學習的,畢竟框架歸根結底的目的不是爲了「標榜本身的特立獨行」,而是「方便廣大開發者」。這是值得思考的一點,不少人彷佛以爲一個框架用了某種模式,另外一個框架就不能用,其實這對於框架之間的進步和發展並無什麼好處。

這裏直接引用尤大在 17 年迴應「Vue 借鑑虛擬 dom」的一段話吧:

再說 vdom。React 的 vdom 其實性能不怎麼樣。Vue 2.0 引入 vdom 的主要緣由是 vdom 把渲染過程抽象化了,從而使得組件的抽象能力也獲得提高,而且能夠適配 DOM 之外的渲染目標。這一點是借鑑 React 毫無爭議,由於我認爲 vdom 確實是個好思想。但要分清楚的是 Vue 引入 vdom 不是由於『react 有因此咱們也要有』,而是由於它確實有技術上的優越性。社區裏基於 vdom 思想造的輪子海了去了,而 ng2 的渲染抽象層和 Ember Glimmer 2 的模板 -> opcode 編譯也跟 vdom 有不少思想上的類似性。

這段話現在用到 Hook 上仍是同樣的適用,程序員都提倡開源精神,怎麼到了 Vue 和 React 之間有些人又變得小氣起來了呢?說的難聽點,Vue 保持本身的特立獨行,那你假如換了一家新公司要你用 Vue,你不是又得從頭學一遍嘛。

更況且 React 社區也同樣有對 Vue 的借鑑,好比你看 react-router@6 的 api,你會發現不少地方和 vue-router 很是類似了。好比 useRoutes 的「配置式路由」,以及在組件中使子路由的代碼結構等等。固然這只是我淺顯的認知,不對的地方也歡迎指正。

擴展閱讀

對於兩種 Hook 之間的區別,想要進一步學習的同窗還能夠看黃子毅大大的好文:

精讀《Vue3.0 Function API》

尤小右在官方 issue 中對於 React Hook 詳細的對比見解:

Why remove time slicing from vue3?

總結

其實總結下來,社區中仍是有一部分的反對觀點是因爲「沒有好好看文檔」形成的,那本文中我就花費本身一些業餘時間整理社區和官方的一些觀點做爲一篇文章,至於看完文章之後你會不會對 Vue3 的見解有所改觀,這並非我能決定的,只不過我很喜歡 Vue3,我也但願可以盡本身的一點力量,讓你們可以不要誤解它。

對於意大利麪代碼:

  1. 提取共用的自定義 Hook(在寫 React 購物車組件的時候,我提取了 3 個以上能夠全局複用的 Hook)。
  2. 基於「邏輯功能」去組織代碼,而不是 state 放在一塊,method 放在一塊,這樣和用 Vue2 沒什麼本質上的區別(不少不少新人在用 React Hook 的時候犯這樣的錯誤,包括我本身)。

對於心智負擔:

  1. 更強大的能力意味着更多的學習成本,可是 Vue3 整體而言我以爲已經把心智負擔控制的很到位了。對於 ref 這個玩意,確實是須要仔細思考一下才能理解。
  2. React Hook 的心智負擔已經重的出名了,在我實際的開發過程當中,有時候真的會被整到頭禿…… 尤爲是抽了一些自定義 Hook,deps 依賴會層層傳遞的狀況下(隨便哪一層的依賴錯了,你的應用就爆炸了)。
  3. 不學習怎麼能升職加薪,迎娶白富美,走向人生巔峯呢!(瞎扯)

Vue3 有多香呢?甚至《React 狀態管理與同構實戰》的做者、React 的忠實粉絲Lucas HC在這篇 Vue 和 React 的優勢分別是什麼? 中都說了這樣的一句話:

我不吐槽更多了:一個 React 粉絲向 Vue3.0 致敬!

Vue3 目前也已經有了 Hook 的一些嘗試:

https://github.com/u3u/vue-hooks

總之,但願看完這篇文章的你,可以更加喜歡 Vue3,對於它的到來我已是期待的不行了。

最後再次強調一下做者的立場,我對於 React 和 Vue 都很是的喜歡。他們都有着各自的優缺點,本文絕無引戰之意。兩個框架都很棒!只是各有優缺點而已。React 的 Immutable 其實也帶來了不少益處,而且 Hook 的思路仍是 Facebook 團隊的大佬們獨創的,真的是很讓人讚歎的設計,我對 React 100% 致敬!

本文的惟一目的就是想消除一些朋友對於 Vue 3.0 的誤解,絕無他意,若有冒犯敬請諒解~

求點贊

若是本文對你有幫助,就點個贊支持下吧,你的「贊」是我持續進行創做的動力,讓我知道你喜歡看個人文章吧~

❤️ 感謝你們

關注公衆號「前端從進階到入院」,有機會抽取「掘金小冊 5 折優惠碼」

關注公衆號加好友,拉你進「前端進階交流羣」,你們一塊兒共同交流和進步。

相關文章
相關標籤/搜索