主頁 > 企業開發 > Vue3 到底哪里好?和React Hook對比有啥有優勢?本文詳解

Vue3 到底哪里好?和React Hook對比有啥有優勢?本文詳解

2020-09-18 08:05:10 企業開發

前言

這幾天 Vue 3.0 Beta 版本發布了,本以為是皆大歡喜的一件事情,但是論壇里還是看到了很多反對的聲音,主流的反對論點大概有如下幾點:

  1. 意大利面代碼結構吐槽:

“太失望了,雜七雜八一堆丟在 setup 里,我還不如直接用 react”

我的天,3.0 這么搞的話,代碼結構不清晰,語意不明確,無異于把 vue 自身優點都扔了

怎么感覺代碼結構上沒有 2.0 清晰了呢 ?? 這要是代碼量上去了是不是不好維護啊

  1. 抄襲 React 吐槽:

抄來抄去沒自己的個性

有 react 香嗎?越來越像 react 了

      3.注意:光理論是不夠的,在此贈送2020最新企業級 Vue3.0/Js/ES6/TS/React/node等實戰視頻教程,想學的可進裙 519293536 免費獲取,小白勿進哦!
在我看來,Vue 黑暗的一天還遠遠沒有過去,很多人其實并沒有認真的去看 Vue-Composition-Api 檔案中的 動機 章節,本文就以這個章節為線索,從 代碼結構底層原理 等方面來一一打消大家的一些顧慮,

在文章的開頭,首先要標明一下作者的立場,我對于 React 和 Vue 都非常的喜歡,他們都有著各自的優缺點,本文絕無引戰之意,兩個框架都很棒!只是各有優缺點而已,React 的 Immutable 其實也帶來了很多益處,并且 Hook 的思路還是 Facebook 團隊的大佬們首創的,真的是很讓人贊嘆的設計,我對 React 100% 致敬!

設計動機

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

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

  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 是相對完美的一種方案,

當然,我的一貫風格就是上代碼對比,我就拿 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>
    <div v-if="error">failed to load</div>
    <div v-else-if="loading">loading...</div>
    <div v-else>hello {{fullName}}!</div>
  </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 = https://www.cnblogs.com/chengxuyuanaa/p/await this.$axios('/api/user')
        this.data = https://www.cnblogs.com/chengxuyuanaa/p/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>
    <div v-if="error">failed to load</div>
    <div v-else-if="loading">loading...</div>
    <div v-else>hello {{fullName}}!</div>
  </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 = https://www.cnblogs.com/chengxuyuanaa/p/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 = https://www.cnblogs.com/chengxuyuanaa/p/"";
    showNewFolder.value = https://www.cnblogs.com/chengxuyuanaa/p/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 帶來的收益抵得過使用它的成本嗎? - 李元秋的回答 - 知乎 www.zhihu.com/question/35…

并且我自己在實際開發中,也遇到了很多問題,尤其是在我想對組件用 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 回傳的 count 和 setCount 則會被保存在組件對應的 Fiber 節點上,每個 React 函式每次執行 Hook 的順序必須是相同的,舉例來說, 這個例子里的 useState 在初次執行的時候,由于執行了兩次 useState,會在 Fiber 上保存一個 { value, setValue } -> { value2, setValue2 } 這樣的鏈表結構,

而下一次渲染又會執行 count 的 useState、 count2 的 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 的一些嘗試:

github.com/u3u/vue-hoo…

  總之,希望看完這篇文章的你,能夠更加喜歡 Vue3,對于它的到來我已經是期待的不行了,
最后注意:光理論是不夠的,在此贈送2020最新企業級 Vue3.0/Js/ES6/TS/React/node等實戰視頻教程,想學的可進裙 519293536 免費獲取,小白勿進哦!

本文的文字及圖片來源于網路加上自己的想法,僅供學習、交流使用,不具有任何商業用途,著作權歸原作者所有,如有問題請及時聯系我們以作處理

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/72106.html

標籤:JavaScript

上一篇:拿2k的前端開發都會做些什么?

下一篇:Vue專案如何部署?實戰教你

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more