Vue3.0 介紹

源碼組織方式
  • 提升代碼可維護(hù)性嚷缭,源碼采用 TypeScript 重寫

  • 使用 Monorepo 管理項(xiàng)目結(jié)構(gòu)厦取,將獨(dú)立模塊提取到不同的包中砂蔽,每個(gè)模塊劃分明確尔苦,模塊依賴關(guān)系也很明確,并且每個(gè)功能模塊都可以單獨(dú)測試提陶、發(fā)布并使用

image-20210412192848527.png

compiler開頭的包都是和編譯相關(guān)的代碼烫沙,compiler-core是和平臺無關(guān)的編譯器,compiler-dom是瀏覽器平臺下的編譯器隙笆,依賴compiler-core锌蓄;compiler-sfc(single file component)單文件組件,用于編譯單文件組件撑柔,依賴compiler-corecompiler-dom瘸爽;compiler-ssr是和服務(wù)端渲染相關(guān)的編譯器,依賴compiler-dom

reactivity是數(shù)據(jù)響應(yīng)式系統(tǒng)铅忿,可單獨(dú)使用

runtime開發(fā)的包都是運(yùn)行時(shí)代碼剪决,runtime-core是和平臺無關(guān)的運(yùn)行時(shí),runtime-dom是針對瀏覽器的運(yùn)行時(shí)檀训,處理原生 DOM API柑潦、事件等;runtime-test是為測試而編寫的輕量的運(yùn)行時(shí)峻凫,渲染出的 DOM 樹是一個(gè) js 對象渗鬼,所以這個(gè)運(yùn)行時(shí)可以運(yùn)行在所有的 js 環(huán)境里,用它來測試渲染是否正確蔚晨,還可以用于序列化 DOM乍钻、觸發(fā) DOM 事件以及記錄某次更新中的 DOM 操作

server-renderer是服務(wù)端渲染

shared是 vue 內(nèi)部使用的一些公共 API

size-check是私有包,不會發(fā)布到 npm铭腕,用于在 tree-shaking 后檢查包的大小

template-explorer是在瀏覽器里運(yùn)行的實(shí)時(shí)編譯組件银择,會輸出 render 函數(shù)

vue構(gòu)建完整版 vue,依賴于compilerruntime

Vue.js3.0 不同構(gòu)建版本

構(gòu)建不同版本累舷,用于不同的場合浩考,和 vue2.x 不同的是,不再構(gòu)建 umd 模塊方式被盈,umd 模塊方式會讓代碼更加冗余

  • packages/vue 存在所有構(gòu)建版本

    image-20210412193022815.png
  • 說明

    官網(wǎng)不同構(gòu)建版本的解釋

    版本 名稱 說明
    cjs(commonJS 模塊化方式析孽, vue.cjs.js 開發(fā)版,代碼未被壓縮
    完整版 vue只怎,包含運(yùn)行時(shí)和編譯器) vue.cjs.prod.js 生產(chǎn)版本袜瞬,代碼被壓縮
    global(全局,這 4 個(gè)文件都可以在瀏覽器中 vue.global.js 完整版身堡,開發(fā)版
    通過 script 的方式引入邓尤,增加全局 vue 對象) vue.global.prod.js 完整版,生產(chǎn)版
    vue.runtime.global.js 運(yùn)行時(shí)版本,開發(fā)版
    vue.runtime.global.props.js 運(yùn)行時(shí)版本汞扎,生產(chǎn)版
    browser(esModule 模塊化方式季稳,在瀏覽器中 vue.esm-browser.js 完整版,開發(fā)版
    通過 type="module"的方式來導(dǎo)入) esm-browser.prod.js 完整版澈魄,生產(chǎn)版
    vue.runtime.esm-browser.js 運(yùn)行時(shí)版本景鼠,開發(fā)版
    vue.runtime.esm-browser.prod.js 運(yùn)行時(shí)版本,生產(chǎn)版
    bundler(需要配合打包工具使用痹扇,使用 es Module vue.esm-bundler.js 完整版铛漓,還導(dǎo)入 runtime-compiler
    方式,內(nèi)部通過 import 導(dǎo)入 runtime-core) vue.runtime.esm-bundler.js 運(yùn)行時(shí)鲫构,通過腳手架創(chuàng)建項(xiàng)目默認(rèn)使用此版本
Composition API

設(shè)計(jì)動(dòng)機(jī)

  • Options API

    包含一個(gè)描述對象組件選項(xiàng)(data票渠、methods、props 等)的對象

    Options API 開發(fā)負(fù)責(zé)組件芬迄,同一個(gè)功能邏輯的代碼被拆分到不同選項(xiàng)中

    export default {
      data() {
        return {
          position: {
            x: 0,
            y: 0,
          },
        }
      },
      created() {
        window.addEventListener(' mousemove ', this.handle)
      },
      destroyed() {
        window.removeEventListener('mousemove ', this.handle)
      },
      methods: {
        handle(e) {
          this.position.x = e.pagexthis.position.y = e.pageY
        },
      },
    }
    
  • Composition API

    Vue.js3.0 中新增的一組 API

    一組基于函數(shù)的 API

    可以更靈活的組織組件的邏輯

    解決超大組件時(shí),使用 Options API 不好拆分和重用問題

    // CompositionAPI
    import { reactive, onMounted, onUnmounted } from 'vue'
    function userMousePosition() {
      const position = reactive({
        x: 0,
        y: 0,
      })
      const update = (e) => {
        position.x = e.pageX
        position.y = e.pageY
      }
      onMounted(() => {
        window.addEventListener('mousemove', update)
      })
      onUnmounted(() => {
        window.removeEventListener('mousemove', update)
      })
      return position
    }
    
    export default {
      setup() {
        const position = useMousePosition()
        return {
          position,
        }
      },
    }
    
    image-20210412200549917.png

同一色塊代表同一功能昂秃,Options API 中相同的代碼被拆分在不同位置禀梳,不方便提取重用代碼

Composition API 同一功能代碼不需要拆分,有利于代碼重用和維護(hù)

  • Composition Api vs Options Api

    • 在邏輯組織和邏輯復(fù)用方面肠骆,Composition API是優(yōu)于Options API
    • 因?yàn)?code>Composition API幾乎是函數(shù)算途,會有更好的類型推斷。
    • Composition APItree-shaking 友好蚀腿,代碼也更容易壓縮
    • Composition API中見不到this的使用嘴瓤,減少了this指向不明的情況
    • 如果是小型組件,可以繼續(xù)使用Options API莉钙,也是十分友好的
性能提升
  • 響應(yīng)式系統(tǒng)升級

    Vue.js2.x 中響應(yīng)式系統(tǒng)核心是 defineProperty廓脆,初始化時(shí)遍歷所有 data 中的成員,通過 defineProperty 將對象屬性轉(zhuǎn)換為 getter 和 setter磁玉,如何 data 中的對象又是對象的話停忿,需要遞歸處理每一個(gè)子對象屬性

    Vue.js3.0 中使用 Proxy 對象重寫響應(yīng)式系統(tǒng),可以攔截屬性的訪問蚊伞、賦值席赂、刪除等操作

    Proxy 好處:

    1. 可以監(jiān)聽動(dòng)態(tài)新增屬性,vue2.x 需要使用$set
    2. 可以監(jiān)聽刪除的屬性时迫,vue2.x 監(jiān)聽不到
    3. 可以監(jiān)聽數(shù)組的索引和 length 屬性颅停,vue2.x 監(jiān)聽不到
  • 編譯優(yōu)化

    對編譯器進(jìn)行優(yōu)化,重寫虛擬 DOM掠拳,首次渲染和 update 性能有了大幅度提升癞揉,這也是Vue3性能能夠得到提升的重要原因之一

    <template>
      <div id="app">
        <div>
          static root
          <div>static node</div>
        </div>
        <div>static node</div>
        <div>static node</div>
        <div>{{ count }}</div>
        <button @click="handler">button</button>
      </div>
    </template>
    

    Vue.js2.x 在構(gòu)建過程中需要先編譯為 render 函數(shù),在編譯時(shí)通過標(biāo)記靜態(tài)根節(jié)點(diǎn),優(yōu)化 diff 過程(但是依然需要執(zhí)行 diff 操作)烧董,當(dāng)組件發(fā)生變化時(shí)毁靶,會通知 watcher,觸發(fā) watcher 的 update 方法逊移,最終執(zhí)行虛擬 DOM 的 patch 操作预吆,遍歷所有虛擬節(jié)點(diǎn)找到差異,然后更新到真實(shí) DOM 上胳泉;diff 過程中會比較整個(gè)虛擬 DOM拐叉,先對比新舊的 div,以及它的屬性扇商,再去對比內(nèi)部子節(jié)點(diǎn)凤瘦;

    Vue.js2.x 中渲染的最小單位是組件

    Vue.js3.0 中標(biāo)記和提升所有靜態(tài)根節(jié)點(diǎn),diff 時(shí)只需要對比動(dòng)態(tài)節(jié)點(diǎn)內(nèi)容

    • Fragments 片段案铺,模板中不需要在創(chuàng)建唯一的根節(jié)點(diǎn)蔬芥,需要升級 vetur 插件,查看Vue 3 Template Explorer

      image-20210413082819879.png

首先使用_createBlock給根 div 創(chuàng)建 block控汉,是樹結(jié)構(gòu)笔诵,然后通過_createVNode創(chuàng)建子節(jié)點(diǎn),相當(dāng)于h函數(shù)姑子,當(dāng)刪除根節(jié)點(diǎn)時(shí)乎婿,會創(chuàng)建_Fragment片段

image-20210413083059655.png
  • 靜態(tài)提升

    打開hoistStatic靜態(tài)提升選項(xiàng),可以看到_createBlock中的靜態(tài)節(jié)點(diǎn)都被提升到 render 函數(shù)外邊街佑,這些節(jié)點(diǎn)只有初始化時(shí)被創(chuàng)建一次谢翎,再次調(diào)用 render 時(shí)不會在被創(chuàng)建

    image-20210413083144478.png
  • Patch flag
image-20210413083558220.png

可以看到在動(dòng)態(tài)節(jié)點(diǎn)<div>{{ count }}</div>通過_createVNode渲染后,最終會有數(shù)字1沐旨,這就是 Patch flag森逮。作為一個(gè)標(biāo)記,將來在執(zhí)行 diff 時(shí)會檢查整個(gè)block中帶 Patch flag 標(biāo)記的節(jié)點(diǎn)希俩,如果 Patch flag 值為1吊宋,代表文本內(nèi)容時(shí)動(dòng)態(tài)綁定,所以只會比較文本內(nèi)容是否發(fā)生變化

image-20210413084010181.png

此時(shí)在給當(dāng)前 div 綁定一個(gè) id 屬性颜武,可以看到 Patch flag 變?yōu)?code>9璃搜,代表當(dāng)前節(jié)點(diǎn)的文本和 PROPS 是動(dòng)態(tài)內(nèi)容,并且記錄動(dòng)態(tài)綁定的 PROPS 是 id鳞上,將來 diff 時(shí)只會檢查此節(jié)點(diǎn)的文本和 id 屬性是否發(fā)生變化这吻,從而提升 diff 性能

  • 緩存事件處理函數(shù)
image-20210413084318107.png

開啟緩存后,首次渲染時(shí)會生成新的函數(shù)篙议,并將函數(shù)緩存到_cache對象中唾糯,將來再次調(diào)用 render 時(shí)怠硼,會從緩存中獲取

  • 源碼體積優(yōu)化

    Vue.js3.0 移除一些不常用 API,如:inline-template移怯、filter 等

    Tree-shaking 支持更好香璃,因?yàn)?Tree-shaking 依賴 ES Module,也就是 ES6 的模塊化語法結(jié)構(gòu)importexport舟误,通過編譯階段的靜態(tài)分析葡秒,找到?jīng)]有引入的模塊,在打包的時(shí)候直接過濾掉嵌溢,從而減少打包體積眯牧。Vue.js3.x 的內(nèi)置組件 keepAlive、Trasition 和一些內(nèi)置指令都是按需引入赖草,并且 Vue.js3.x 中的很多 API 都是支持 Tree-shaking学少,沒有使用是不會進(jìn)行打包的

Vite

學(xué)習(xí) Vite 前,先需要了解 ES Module

  • 除 IE 外秧骑,現(xiàn)代瀏覽器都支持 ES Moduie

  • 加載模塊通過在 script 標(biāo)簽中 type="module"即可

    <script type="module" src="..."></script>
    
  • 支持模塊的 script 默認(rèn)延遲加載

    類似于 script 標(biāo)簽設(shè)置 defer

    在文檔解析完成后版确,觸發(fā)DOMContentLoaded事件前執(zhí)行

案例項(xiàng)目地址

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">Hello world!</div>
    <script>
      window.addEventListener('DOMContentLoaded', () => {
        console.log('DOMContentLoaded')
      })
    </script>
    <script type="module" src="./modules/index.js"></script>
  </body>
</html>
// modules/index.js
import { forEach } from './utils.js'

const app = document.querySelector('#app')
console.log(app.innerHTML)

const arr = [1, 2, 3]
forEach(arr, (item) => {
  console.log(item)
})

type="module"方式引入時(shí)需要在服務(wù)器中運(yùn)行項(xiàng)目,在 vsCode 中安裝插件live-server乎折,右鍵啟動(dòng)項(xiàng)目

image-20210413103509503.png

打開瀏覽器控制臺阀坏,可以看到輸出結(jié)果如下所示,可以看到index.js模塊在文檔解析完成后笆檀,觸發(fā) DOMContentLoaded 事件前執(zhí)行

image-20210413085620461.png

Vite vs Vue-Cli

  • Vite 在開發(fā)模式下不需要打包可以直接運(yùn)行,因?yàn)?vite 在開發(fā)模式下使用瀏覽器支持的 es Module 加載模塊盒至,通過<script type="module"></script>的方式加載代碼酗洒,提升開發(fā)效率;vite 會開啟測試服務(wù)器枷遂,攔截瀏覽器發(fā)送請求樱衷,對瀏覽器不識別的模塊進(jìn)行處理,比如當(dāng) import 單文件組件時(shí)酒唉,會先進(jìn)行編譯矩桂,把編譯的結(jié)果發(fā)送給瀏覽器
  • Vue-Cli 開發(fā)模式下必須對項(xiàng)目打包才可以運(yùn)行
  • Vite 在生成環(huán)境下使用 Rollup 打包,基于 ES Module 的方式打包痪伦,不再需要使用 babel 把 import 轉(zhuǎn)換為 require侄榴,因此打包體積會小于 webpack 體積
  • Vue-Cli 使用 Webpack 打包

Vite 特點(diǎn)

  • 快速冷啟動(dòng)(不需要打包)
  • 按需編譯(代碼加載時(shí)才會進(jìn)行編譯)
  • 模塊熱更新

使用 Vite 創(chuàng)建基于 vue3 項(xiàng)目

npm install create-vite-app -g
npm init vite-app <project-name>
cd <project-name>
npm install
npm run dev

基于模板創(chuàng)建項(xiàng)目

npm init vite-app --template react
npm init vite-app --template preact

案例項(xiàng)目地址

通過 create-vite-app 創(chuàng)建完項(xiàng)目之后,App.vue 會有 eslint 語法錯(cuò)誤网沾,原因是 Vetur 插件還沒有更新

image-20210413085824316.png

解決:文件 --> 首選項(xiàng) --> 設(shè)置 --> 搜索 eslint-plugin-vue --> Vetur ? Validation: Template 取消勾選

image-20210413095847513.png

通過 npm run dev 啟動(dòng)項(xiàng)目

開發(fā)環(huán)境下癞蚕,vite 開啟 web 服務(wù)器后,會劫持.vue 結(jié)尾的文件辉哥,將.vue 文件轉(zhuǎn)換為 js 文件桦山,并將響應(yīng)中的 content-type 設(shè)置為 application/javascript攒射,告訴瀏覽器是 js 腳本

image-20210413113538441.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市恒水,隨后出現(xiàn)的幾起案子会放,更是在濱河造成了極大的恐慌,老刑警劉巖钉凌,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咧最,死亡現(xiàn)場離奇詭異,居然都是意外死亡甩骏,警方通過查閱死者的電腦和手機(jī)窗市,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來饮笛,“玉大人咨察,你說我怎么就攤上這事「G啵” “怎么了摄狱?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長无午。 經(jīng)常有香客問我媒役,道長,這世上最難降的妖魔是什么宪迟? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任酣衷,我火速辦了婚禮,結(jié)果婚禮上次泽,老公的妹妹穿的比我還像新娘穿仪。我一直安慰自己,他們只是感情好意荤,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布啊片。 她就那樣靜靜地躺著,像睡著了一般玖像。 火紅的嫁衣襯著肌膚如雪紫谷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天捐寥,我揣著相機(jī)與錄音笤昨,去河邊找鬼。 笑死握恳,一個(gè)胖子當(dāng)著我的面吹牛咬腋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播睡互,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼根竿,長吁一口氣:“原來是場噩夢啊……” “哼陵像!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起寇壳,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤醒颖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后壳炎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體泞歉,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年匿辩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了腰耙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,064評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡铲球,死狀恐怖挺庞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情稼病,我是刑警寧澤选侨,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站然走,受9級特大地震影響援制,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜芍瑞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一晨仑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拆檬,春花似錦寻歧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽猾封。三九已至澄耍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間晌缘,已是汗流浹背齐莲。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留磷箕,地道東北人选酗。 一個(gè)月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像岳枷,于是被迫代替她去往敵國和親芒填。 傳聞我的和親對象是個(gè)殘疾皇子呜叫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友殿衰。感恩相遇朱庆!感恩不離不棄。 中午開了第一次的黨會闷祥,身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,551評論 0 11
  • 彩排完娱颊,天已黑
    劉凱書法閱讀 4,187評論 1 3
  • 表情是什么,我認(rèn)為表情就是表現(xiàn)出來的情緒凯砍。表情可以傳達(dá)很多信息箱硕。高興了當(dāng)然就笑了,難過就哭了悟衩。兩者是相互影響密不可...
    Persistenc_6aea閱讀 124,187評論 2 7