VUE 3.0 學習探索入門系列 - vue2.x/React/vue3.x 簡單橫評(4)

1 Vue 回顧

Vue.js 是 漸進式 的 JavaScript 框架。什麼是 漸進式(Progressive) ?就是由淺入深,一步一步的,爲何 Evan You 說 Vue.js 是漸進式的框架呢?javascript

  • Vue 的核心庫只關注視圖層,不只易於上手,還便於與第三方庫或既有項目整合;
  • 現代化的工具鏈 以及各類 支持類庫 結合使用時,Vue也徹底可以爲複雜的單頁應用提供驅動

Vue.js 有啥特色呢?html

  • 容易上手
  • 生態豐富完整
  • 文檔清晰明瞭

固然,若是想更全面的瞭解 Vue,對比 React 和 Angular 等框架,能夠看看這裏的 橫向對比前端

參考資料:cn.vuejs.org/v2/guide/vue

Vue2.xjava

Vue 自誕生開始,每個大版本都在進步,相比 Vue1.x 而言,咱們如今使用的 Vue 2.x 效果:react

  • 更小,vue、vue-router 和 vuex 三個加一塊兒,跟 Vue1.0 的核心庫大小同樣
  • 更快,基本是當前最快的框架,查看測試對比
  • 支持SSR 和 原生渲染

參考資料:juejin.im/entry/58102…webpack

Vue3.xgit

相比 Vue2.x 而言,Vue3.x 的設計目標:github

  • 更小
  • 更快
  • 增強 TypeScript 支持
  • 增強 API 設計一致性
  • 提升自身可維護性
  • 開放更多底層功能

參考資料:img.w3ctech.com/VueConf2019…web

Evan You 爲何制定 Vue3.x 的這些目標呢?可能你們要先了解下 Vue2.x 的現狀。

2 Vue 和 React 逃不掉的話題

2.1 Vue 和 React 哪一個更好?

整體一個觀點:衆口難調!

整體一個原則:沒有絕對好的框架,也沒有絕對差的框架。每一個人仍是從各方面(自身技術能力、團隊技術基礎、上手成本、項目特色)考慮,選擇一款適合本身的框架爲好。

如下是 Evan You 對 Vue 和 React 對比的自我評價:

  • 若是多年之後要論歷史地位,React 確定是高於 Vue 的。事實上,我做爲一個開發者,也是由衷地佩服 Jordan Walke, Sebastian Markbage 這樣的,能從開發模式層面上提出突破性的新方向的人。
  • React 從一開始的定位就是提出 UI 開發的新思路;Vue 從一開始的定位就是儘量的下降前端開發的門檻,讓更多的人可以更快地上手開發

瞭解詳情:www.zhihu.com/question/30…

One more thing

補充一點 Evan you 對 Vue 和 Angular 對比的自我評價:

瞭解詳情:www.zhihu.com/question/40…

2.2 Vue 對於 Ts 的支持不夠友好?

整體評價:Vue2.x 支持顯然跟 React 和 Angular 是有差距的。

如下是 Evan You 對 Ts 的自我評價:

  • 現有的 API 和類型系統的結合存在缺陷,屬於歷史遺留,改新的 API 有個時機問題,因此 Vue3 出現了
  • TSX 類型支持好是由於 Ts 專門開了後門給作了支持,模版只要工具鏈到位同樣能夠作到
  • Vue 2 一開始內部實現就有類型系統,可是沒想到 Flow 爛尾了,而 Ts 整個生態越作越好,這個屬於就是押錯寶了,只能說...Ts 真香!

瞭解詳情:www.zhihu.com/question/31…

One more thing

另外 Evan You 當初爲何選擇使用 Flow ,而不是直接上 Ts

看這裏:www.zhihu.com/question/46…

2.3 Vue 更適合中小項目?

首先來看看知乎上的一個帖子,你們討論的熱火朝天:爲何react比vue更適合大型應用?

在我以前的面試中,當問到如何看待 React 和 Vue 這2個框架的時候,也有很多的人的回答是:Vue 適合中小項目,React 適合大型項目!

其實,在回答這個問題以前,你們首先得弄明白 「什麼是中小項目?什麼是大型項目?」 若是這個標準不統一,那你們爭論是沒有意義的。

就比如,什麼是大前端?什麼是前端工程化?這是個人理解

其實業界也沒有太多定義,如下是我的觀點(歡迎指正),大型項目知足其一就行:

  • 老闆層面:項目經費超過 1000w
  • 經理層面:參與總人數超過 100人
  • 產品層面:核心需求總數超過 500個
  • 技術層面:代碼行數超過 10w行

除此以外,都應該算做中小項目。

若是按照以上標準劃分大中小型項目的話,你們平時有機會接觸到的大項目有多少呢?

更況且,爲了下降風險,除非沒法拆分,否則通常公司裏面大型項目也會被拆分紅多箇中小項目落地。因此,我要說的是,你們不必從這個角度來劃分一個前端框架,意義不大。

只是從人們的認知裏面,通常認爲的大型項目會出現如下問題,好比:

  • 前期考慮不周,後期簡直沒法維護
  • 人員能力良莠不齊,代碼質量很難保證
  • 人數衆多,溝通交流成本過高
  • 各作各的,冗餘代碼多,冗餘組件多
  • 接口設計太難,組件複用更難
  • 作兩年可能就爛尾了,或者領導跑路了
  • 50%以上的功能都是產品異想天開,其實用戶不多用!
  • 爲了趕進度,1.0每每都作的跟翔同樣
  • ...

好了,其實按個人理解,與其說是用項目大小來決定該選擇哪一個框架,不如從自身遇到問題出發衡量下適合本身的框架,由於以上問題不止大型項目的問題,全部項目均可能會遇到。

2.4 Vue3.x setup 和 React hooks 對比

  • 總的來講 setup 更符合 JS 的標準;
  • 對調用順序不敏感,同時也能夠有條件;
  • setup 僅被調用一次,併產生較小的GC壓力;
  • 無需考慮 useCallback 幾乎老是須要在哪兒防止內聯處理程序致使子組件的過分渲染的問題;
  • 也無需考慮 useEffect 和 useMemo 產生的無用的變量,當用戶使用了 watchers 或者 computed 的值,在天然失效之後

Vue setup 的思路借鑑了 React hooks 的靈感,同時也解決了 hooks 存在的上面的問題。

參考資料:vue-composition-api-rfc.netlify.com/#comparison…

2.5 我的觀點 React 對比 Vue

簡單對比下 React 和 Vue(我的理解和翻閱相關資料,歡迎批量指正,不引戰!輕點噴!):

  1. React 更加擁抱 函數式編程 的思想,函數是一等公民;而 Vue2.x 更像是面向對象編程,AOP(切面)思想體現明顯,好比:Options 一堆鉤子的設計。到底哪一個更好?隨着 Vue3.x 的發佈,答案就明瞭(下文會說)!
  2. React 一直是 Facebook 大公司維護;Vue 是我的做品,雖然到如今爲止有 20人左右 的核心參與者,可是看 Github 提交記錄(vuejs/vue工程),絕大多數代碼仍是 Evan You 提交維護(90%以上),其餘人主要負責生態中的其餘系統。這個會不會影響你選擇使用哪一個框架呢?我以爲至少在 Vue2.x 時代的時候,確定有一些大的團隊會優先考慮穩定性,畢竟歷史上爛尾的例子太多了(近在眼前的 Flow 不就是麼?偷笑)。
  3. 上面有提到 React 結合 Ts 開發,約束更強,規矩更多,對項目的風險把控較高;而 Vue2.x 對 Ts 支持天生較弱(上面已經仔細說了,沒辦法壓錯寶!),因此,對於使用 Ts 就回不去的人來講,簡直沒法忍受!但也不是不能用,只是有些弱(就個你用了Mac,就再回不到Windows同樣)。
  4. 性能方面,大多數狀況下 不分伯仲,更況且誰會傻到一個頁面for循環幾萬條數據?或者組件嵌套10層以上呢?若是遇到我以爲須要優化產品,或者重構架構。
  5. 爲何對於 Vue3.x 你們都以爲愈來愈像 React?那是因爲 Vue3.x 面對當前不足,借鑑了 React 的一些優勢,彌補了本身的不足,好比:函數式編程、Ts 支持!因此,他們愈來愈像!
  6. 最後,若是說 Vue2.x 是 Evan you 基於各大門派獨闢蹊徑的一個輕量級、低門檻上手的框架的話,Vue3.x 更像是一個基於 React,將函數式編程這個自由發揮的編程思想從新包裝,推出 Composition API,使其更有章法,更加規範的一個框架。

關於 Vue3.x

通過了上面各類對比,咱們回過頭來再看看 Vue3.x 改進:

3.1 Options API 到 Composition API 的轉變

這實際上是由徹底面向對象OOP的思路,到函數式編程的思想轉變。

只不過提及函數式編程你們看看文檔可能都知道概念,無非業務邏輯都是一個個函數實現嘛!可是,真讓你在項目裏自由發揮寫那麼多函數的時候,你該怎麼寫?(這可能也是你們以爲 React 不太容易上手的以一個緣故吧,喜歡被 Vue 安排的明明白白!)

因而結合着 Vue2.x 裏面的 Options API,將之前徹底按照AOP模式的Options API,細粒度拆分紅細小的函數,而後統一放到 setup 這一個入口函數中調用!雞賊!佩服!

這樣作的3個好處:

  1. 既保留了 Vue2.x 中各個函數的功能,作到兼容
  2. 同時以小的函數形式被調用,更加靈活,更好維護,更好 tree-shaking
  3. 最後還能將你們頭痛的不知道如何函數式編程的痛點,安排明白一些(Composition API)

可謂:一石三鳥

下面以示例的形式來解釋下這個概念。

好比 Vue2.x 時對於一個獨立組件:

開始只有簡單的鼠標處理邏輯。

export default {
    data() {
        return {
            x: 0,
            y: 0
        }
    },
    mounted() {
        window.addEventListener('mousemove', this.update)
    },
    methods: {
        update(e) {
            this.x = e.pageX
            this.y = e.pageY
        }
    },
    destroyed() {
        window.removeEventListener('mousemove', this.update)
    }
}
複製代碼

以上會存在什麼問題呢?舉例來講明:

隨着時間的推移,這個組件可能會發展成以下的模樣!

export default {
    data() {
        return {
            x: 0,
            y: 0,
            a: 0,
            b: 0,
            c: 0,
            d: 0,
            e: 0,
            f: 0,
            g: 0,
            h: 0,
            i: 0,
            j: 0,
            k: 0,
            l: 0,
            m: 0,
            n: 0 // 算了寫不下去了。。。總之 data 可能會有不少
        }
    },
    mixins: [
        a,
        b,
        c,
        d,
        e,
        f // 算了,寫不下去了,總之爲了拆分代碼,mixins 已經讓我寫到吐了
    ],
    mounted() {
        window.addEventListener('mousemove', this.update)
        
        // TODO 接下來可能會有一堆頁面渲染完成的邏輯在這裏哦
        
        // 這裏是業務邏輯1
        // if / else if / else
        
        // 下面是業務邏輯2
        // while 
        
        // 哎呀全部的事情,都須要在頁面渲染完去作呀,沒辦法
        // switch
        
        // 算了,寫不下去了。。。
        // 跑路。。。
    },
    methods: {
        update(e) {
            this.x = e.pageX
            this.y = e.pageY
        },
        // 下面有一堆方法等着你哦
        method1() {
            // 預留着,方法只能放到 methods 對象下啊
        },
        method2() {
            // 張三的註釋
            // 一堆邏輯
        },
        method3() {
            // ... 跑路了。。。
        }
    },
    destroyed() {
        window.removeEventListener('mousemove', this.update)
    }
}
複製代碼

你們看出來上面的代碼的問題了麼?由於你們必須在 Vue 規定的條條框框裏面寫東西,因此,尤爲初學者,會把一個簡單的組件,寫到簡直沒法直視的地步!

那你可能要說了,以上代碼是有不少解決辦法的呀,好比下面2種常見的優化方案:

一、將這個文件拆分紅多個子組件或者模塊

好比:若是按模塊拆分,能夠把 data 拆分紅一個js文件,methods 拆分紅一個 js 文件,等等。這麼作只是至關於把一堆代碼打散而已,代碼連貫性、可維護性方面,變得更糟了。

再好比:拆分紅多個子組件,每一個子組件實現一塊邏輯!(這是強拆!)你們拆分組件的原則,確定不是基於代碼量去拆的吧!因此,這會讓業務模塊,變得支離破碎,難以理解和維護。

二、使用 mixins 提取公共代碼

mixins 解決的是公共的代碼混入複用,若是隻是一個組件過於龐大,你拆分到 mixins 多個文件中,有啥意義呢?跟上面的強拆有啥區別?

更況且,即使有複用的代碼,若是一個文件中引入 10個以上的 mixin 文件,裏面的 data 可能會覆蓋,methods 可能會覆蓋,你知道哪一個生效了?template 使用的變量,你知道來自哪裏?

對於上面的示例,Vue3.x 的解決辦法

定義獨立文件 mouse.js

這個文件就只處理鼠標事件!業務和代碼邏輯都在一塊兒,好理解,易於維護。

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 }
}
複製代碼

main.vue 引入文件

這裏的代碼量也變的不多,很清晰。

import { useMousePosition } from './mouse'

export default {
  setup() {
    const { x, y } = useMousePosition()
    // other logic...
    return { x, y }
  }
}
複製代碼

示例參考:vue-composition-api-rfc.netlify.com/#logic-extr…

若是遇到不一樣的業務模塊,就單獨到獨立文件或者模塊處理,而後引入便可,好比:

(下面的邏輯若是在 vue2.x 中還真不太好處理!)

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
    }
  }
}
複製代碼

參考代碼:vue-composition-api-rfc.netlify.com/#code-organ…

看了以上代碼有啥感想?我本身的感覺:

  • 若是代碼量不大,組件比較小的狀況下,我更喜歡 Vue2.x 的語法(被安排)。
  • 若是業務集中,組件複雜,我更喜歡 Vue3.x 的寫法。好在至少目前獲得的消息,Vue3.x 會大部分兼容 Vue2.x 的特性,贊!

3.2 更好的支持 Ts

Vue2.x 寫法:

import { Component, Prop, Vue } from 'vue-property-decorator'

@Component
export default class HelloWorld extends Vue {
  @Prop() private message!: string;

  data (): object {
    // this.message
  }
}
複製代碼

Vue3.x 寫法:

import { defineComponent } from 'vue'
export default defineComponent({
  props: {
    message: String
  },
  setup(props, context) {
    // setup 中沒法使用 this 關鍵詞
    
    // props.message
    // context.attrs
    // context.slots
    // context.emit
  }
})
複製代碼

對比下,至少寫法上更簡單,並且不用在使用那麼多的 裝飾器 了!

3.3 其餘

再回過頭來看看 Evan You 對 Vue3.x 的目標定義:

  • 更小
  • 更快
  • 增強 TypeScript 支持 上文已說明
  • 增強 API 設計一致性 上文已說明
  • 提升自身可維護性 上文已說明
  • 開放更多底層功能

更小

對比了 vue@3.0.0-alpha.8vue@2.6.11 這2個版本的未壓縮版本的文件大小:

單純從這2個獨立的版本看,3.0還變大了!

因此,我的認爲,真正要能變小,可能仍是要放到工程化體系中,依賴編譯器,好比:webpack,而後基於 3.0 這種函數式編程更好 tree shaking 的機制,最終打包編譯後的效果而言。

更快

Vue3.x 如下重大變化:

  • 數據綁定策略由 Object.defineProperty() 換成了 new Proxy()
  • 重構了Virtual DOM
  • 更多編譯時優化,如:Slot 默認編譯爲函數

參考地址:img.w3ctech.com/VueConf2019…

理論上性能上確定要比以前好(至少 Proxy 就更高效一些),可是這個目前還很差驗證,相信正式 Release 後續官方也會給出一些數據,同時圈內確定也會有不少測試結果出爐。

開放更多底層功能

這個目前還不太清楚,等官方出爐吧。

(本文完)

相關文章
相關標籤/搜索