最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3 編譯流程-源碼解析

 更新時(shí)間:2021年09月25日 11:11:21   作者:Originalee  
今天將從 Vue 的入口文件開始,看看聲明了一個(gè) Vue 的單文件之后是如何被 compile-core 編譯核心模塊編譯成渲染函數(shù)的。下面小編講解并附上代碼分析展現(xiàn)在文章里,感興趣的小伙伴不要錯(cuò)過(guò)奧

前言:

Vue3 發(fā)布已經(jīng)很長(zhǎng)一段時(shí)間了,最近也有機(jī)會(huì)在公司項(xiàng)目中用上了 Vue3 + TypeScript + Vite 的技術(shù)棧,所以閑暇之余抽空也在抽空閱讀 Vue3 的源碼。本著好記性不如爛筆頭的想法,在閱讀源碼時(shí)順便記錄了一些筆記,也希望能爭(zhēng)取寫一些源碼閱讀筆記,幫助每個(gè)想看源碼但可能存在困難的同學(xué)減少理解成本。

Vue2.x 的源碼我也有過(guò)一些簡(jiǎn)單的閱讀,自 Vue3 重構(gòu)后,Vue 項(xiàng)目的目錄結(jié)構(gòu)也發(fā)生了很大的變化,各個(gè)功能模塊被分別放入了 packages 目錄下,職責(zé)更加清晰,通過(guò)目錄名就可以一目了然。今天將從 Vue 的入口文件開始,看看聲明了一個(gè) Vue 的單文件之后是如何被 compile-core 編譯核心模塊編譯成渲染函數(shù)的。

為了大家的閱讀方便,以及控制文章篇幅,我會(huì)把閱讀源碼時(shí)不太需要在意的邏輯進(jìn)行折疊,或者通過(guò)注釋 /* 忽略邏輯 */ 這樣的標(biāo)識(shí)進(jìn)行忽略處理。

我個(gè)人是不太喜歡在看源碼分析文章時(shí)一上來(lái)就懟出一大段代碼,這容易讓沒(méi)閱讀的同學(xué)有點(diǎn)懵逼。所以這個(gè)系列的文章我會(huì)盡量對(duì)關(guān)鍵的代碼畫出一張流程圖。目的還是一個(gè),幫助大家降低理解成本,同時(shí)也讓各位同學(xué)在下次自主閱讀時(shí)有張流程圖能參考。

1、解讀Vue 入口文件

我們會(huì)先從一個(gè) Vue 對(duì)象的入口來(lái)開始我們的源碼閱讀, packages/vue/index.ts 。這個(gè)入口文件的代碼比較簡(jiǎn)單,只有一個(gè) compileToFunction 函數(shù),但函數(shù)體內(nèi)的內(nèi)容卻又比較關(guān)鍵,所以先看一張圖,來(lái)理解這個(gè)函數(shù)體究竟完成了哪些事情。

在看完流程圖之后,我們來(lái)對(duì)照代碼一起看,我相信大部分同學(xué)在此時(shí)可能對(duì)下發(fā)圖片中的代碼一目了然了。

直接跳過(guò)所有代碼,看文件的末尾 35 行,調(diào)用了 registerRuntiomCompiler 函數(shù),將 compileToFunction 函數(shù)作為參數(shù)傳入,這行代碼即對(duì)應(yīng)流程圖的起始,通過(guò)依賴注入的方式,將 compile 函數(shù)注入至 runtime 運(yùn)行時(shí)中,依賴注入是一種比較巧妙的解耦方式,此時(shí)運(yùn)行時(shí)再調(diào)用 compile 編譯函數(shù),就是在調(diào)用當(dāng)前的 compileToFunction 函數(shù)了。

再看代碼中的第 17 行,調(diào)用了 compile-dom 庫(kù)提供的 compile 函數(shù),從返回值中解構(gòu)出了 code 變量。這個(gè)就是編譯器執(zhí)行之后生成的編譯結(jié)果,code 是編譯結(jié)果的其中一個(gè)參數(shù),是一個(gè)代碼字符串。比如

<template>
  <div>
    Hello World
  </div>
</template>

這個(gè)簡(jiǎn)單的模板,在經(jīng)過(guò)編譯后,code 返回的字符串為

const _Vue = Vue return function render(_ctx, _cache) {  with (_ctx) {    const { openBlock: _openBlock, createBlock: _createBlock } = _Vue     return (_openBlock(), _createBlock("div", null, "Hello World"))  } }

這個(gè)神奇的 compile 函數(shù)內(nèi)部的奧妙在之后我會(huì)詳細(xì)講解。

在拿到這個(gè)這個(gè)代碼字符串的結(jié)果后,我們?cè)夙樦a往下看,第 25 行聲明了一個(gè) render 變量,并且將生成的代碼字符串 code 作為參數(shù)傳入了 new Function 構(gòu)造函數(shù)。這就是流程圖中的倒數(shù)第二步,生成了 render 函數(shù)??梢詫⑽曳旁谏厦娴?code 字符串格式化,能夠發(fā)現(xiàn) render 函數(shù)是一個(gè)柯里化的函數(shù),返回了一個(gè)函數(shù),函數(shù)內(nèi)部通過(guò) with 來(lái)擴(kuò)展作用域鏈。

而最后入口文件返回了 render 變量,并且順手緩存了 render 函數(shù)。

上方源碼的第 1 行,我們看到入口文件創(chuàng)建了一個(gè) compileCache 對(duì)象,用以緩存 compileToFunction 函數(shù)生成的 render 函數(shù),將 template 參數(shù)作為緩存的 key, 并在 11 行的位置有一個(gè) if 分支做緩存的判斷,如果該模板之前被緩存過(guò),則不再進(jìn)行編譯,直接返回緩存中的 render 函數(shù),以此提高性能。

至此 package/vue/index.ts 的入口文件就解讀完了。相信大家也都看出來(lái)了,最有意思的部分就是調(diào)用 compile 函數(shù)編譯出了代碼字符串,所以接下來(lái)我將圍繞 compile 函數(shù)來(lái)接著嘮。compile 函數(shù)牽扯到 compile-dom compile-core 兩個(gè)模塊,本篇文章我只會(huì)解讀關(guān)鍵流程。細(xì)節(jié)分析的話會(huì)放在后續(xù)文章中。一起來(lái)看一下 compile 的運(yùn)行流程:

 2、compile 的運(yùn)行流程

compile 函數(shù)內(nèi)部直接返回 baseCompile 函數(shù)的結(jié)果,而 baseCompile 函數(shù)在執(zhí)行過(guò)程中會(huì)生成 AST 抽象語(yǔ)法樹,并調(diào)用 transform 對(duì) 每個(gè) AST 節(jié)點(diǎn)進(jìn)行處理,例如轉(zhuǎn)換vOn、v-if、v-for 等指令,最后將處理后的 AST 抽象語(yǔ)法樹通過(guò) generate 函數(shù)生成之前提及的代碼字符串,并返回編譯結(jié)果,至此 compile 函數(shù)執(zhí)行完畢。明白了大體的流程后,接著來(lái)看源碼。

compile 函數(shù)的源碼路徑是 packages/compiler-dom/src/index.ts, 我們看到在 compile 的函數(shù)體內(nèi),直接 return 了 baseCompile 的處理結(jié)果。而 baseCompile 的源碼路徑是 packages/compiler-core/src/compile.ts 。為什么會(huì)有 baseCompile 這樣的命名呢?因?yàn)?code> compile-core 是編譯的核心模塊,接受外部的參數(shù)來(lái)按照規(guī)則完成編譯,而 compile-dom 是專門處理瀏覽器場(chǎng)景下的編譯,在這個(gè)模塊下導(dǎo)出的 compile 函數(shù)是入口文件真正接收的編譯函數(shù)。而 compile-dom 中的 compile 函數(shù)相對(duì) baseCompile 也是更高階的一個(gè)編譯器。例如當(dāng) Vue 在 weex 在 iOS 或者 Android 這些 Native App 中工作時(shí),compile-dom 可能會(huì)被相關(guān)的移動(dòng)端編譯庫(kù)來(lái)取代。

順著往下一起看一下 baseCompile 函數(shù):

先從函數(shù)聲明中來(lái)看,baseCompile 接收 template 模板以及上層高階編譯器中處理過(guò) options 編譯選項(xiàng),最終返回一個(gè) CodegenResult 類型的編譯結(jié)果。

export interface CodegenResult {
  code: string
  preamble: string
  ast: RootNode
  map?: RawSourceMap
}

通過(guò) CodegenResult 的接口聲明能清晰的看到返回結(jié)果中存在 code 代碼字符串、處理后的 AST 抽象語(yǔ)法樹,以及 sourceMap。

看上方源碼的第 12 行,判斷 template 模板是否為字符串,如果是的話則會(huì)對(duì)字符串進(jìn)行解析,否則直接將 template 作為 AST 。其實(shí)我們平時(shí)在寫的單文件 vue 代碼,都是以字符串的形式傳遞進(jìn)去的。

接下來(lái)源碼是 16 行調(diào)用了 transform 函數(shù),以及傳入了指令轉(zhuǎn)換、節(jié)點(diǎn)轉(zhuǎn)換等工具函數(shù),對(duì)由模板生成的 AST 進(jìn)行轉(zhuǎn)換。

最終的 32 行位置,我們將轉(zhuǎn)換好的 AST 傳入 generate,生成 CodegenResult 類型的返回結(jié)果。

在 compile-core 模塊中,AST 解析、transform、codegen、compile、parse 這些函數(shù)都是一個(gè)單獨(dú)的小模塊,內(nèi)部的實(shí)現(xiàn)都非常精妙,在編譯器的后續(xù)文章中,會(huì)逐個(gè)進(jìn)行介紹。

本文通過(guò)從入口文件開始,對(duì)編譯的大體流程進(jìn)行解釋,希望可以幫助大家在閱讀編譯器這個(gè)模塊的代碼時(shí)能有一個(gè)清晰的流程概念,配合流程圖食用更香喲。

到此這篇關(guān)于Vue3 編譯流程-源碼解析的文章就介紹到這了,更多相關(guān)Vue3 編譯流程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue中uni-app 實(shí)現(xiàn)小程序登錄注冊(cè)功能

    vue中uni-app 實(shí)現(xiàn)小程序登錄注冊(cè)功能

    這篇文章主要介紹了uni-app 實(shí)現(xiàn)小程序登錄注冊(cè)功能,文中給大家介紹了實(shí)現(xiàn)思路,以及vuex和本地緩存的區(qū)別,需要的朋友可以參考下
    2019-10-10
  • 解決Vue+Element ui開發(fā)中碰到的IE問(wèn)題

    解決Vue+Element ui開發(fā)中碰到的IE問(wèn)題

    今天小編就為大家分享一篇解決Vue+Element ui開發(fā)中碰到的IE問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09
  • 配置vite.confgi.ts無(wú)法使用require問(wèn)題以及解決

    配置vite.confgi.ts無(wú)法使用require問(wèn)題以及解決

    這篇文章主要介紹了配置vite.confgi.ts無(wú)法使用require問(wèn)題以及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • vue如何基于el-table實(shí)現(xiàn)多頁(yè)多選及翻頁(yè)回顯過(guò)程

    vue如何基于el-table實(shí)現(xiàn)多頁(yè)多選及翻頁(yè)回顯過(guò)程

    在最近的一個(gè)項(xiàng)目中我需要實(shí)現(xiàn)表格的翻頁(yè),并且還要實(shí)現(xiàn)全選、多選功能,下面這篇文章主要給大家介紹了關(guān)于vue如何基于el-table實(shí)現(xiàn)多頁(yè)多選及翻頁(yè)回顯過(guò)程的相關(guān)資料,需要的朋友可以參考下
    2022-12-12
  • Vue中輸入框僅支持?jǐn)?shù)字輸入的四種方法

    Vue中輸入框僅支持?jǐn)?shù)字輸入的四種方法

    項(xiàng)目中需要用到大量的數(shù)字輸入框限制,為了可以以后能又更多的拓展性,下面這篇文章主要給大家介紹了關(guān)于Vue中輸入框僅支持?jǐn)?shù)字輸入的四種方法,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-08-08
  • uniapp Vue3中如何解決web/H5網(wǎng)頁(yè)瀏覽器跨域的問(wèn)題

    uniapp Vue3中如何解決web/H5網(wǎng)頁(yè)瀏覽器跨域的問(wèn)題

    存在跨域問(wèn)題的原因是因?yàn)闉g覽器的同源策略,也就是說(shuō)前端無(wú)法直接發(fā)起跨域請(qǐng)求,同源策略是一個(gè)基礎(chǔ)的安全策略,但是這也會(huì)給uniapp/Vue開發(fā)者在部署時(shí)帶來(lái)一定的麻煩,這篇文章主要介紹了在uniapp Vue3版本中如何解決web/H5網(wǎng)頁(yè)瀏覽器跨域的問(wèn)題,需要的朋友可以參考下
    2024-06-06
  • vscode配置@路徑提示方式,并解決vue文件內(nèi)失效的問(wèn)題

    vscode配置@路徑提示方式,并解決vue文件內(nèi)失效的問(wèn)題

    這篇文章主要介紹了vscode配置@路徑提示方式,并解決vue文件內(nèi)失效的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • 詳解vue2.6插槽更新v-slot用法總結(jié)

    詳解vue2.6插槽更新v-slot用法總結(jié)

    在 2.6.0 中,我們?yōu)榫呙宀酆妥饔糜虿宀垡肓艘粋€(gè)新的統(tǒng)一的語(yǔ)法 (即 v-slot 指令)。這篇文章主要介紹了詳解vue2.6插槽更新v-slot用法總結(jié),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-03-03
  • elementui實(shí)現(xiàn)標(biāo)簽頁(yè)與菜單欄聯(lián)動(dòng)的示例代碼

    elementui實(shí)現(xiàn)標(biāo)簽頁(yè)與菜單欄聯(lián)動(dòng)的示例代碼

    多級(jí)聯(lián)動(dòng)是一種常見的交互方式,本文主要介紹了elementui實(shí)現(xiàn)標(biāo)簽頁(yè)與菜單欄聯(lián)動(dòng)的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-06-06
  • Vue3狀態(tài)管理的使用詳解

    Vue3狀態(tài)管理的使用詳解

    這篇文章主要介紹了Vue3狀態(tài)管理的使用詳解,幫助大家更好的理解和學(xué)習(xí)使用vue框架,感興趣的朋友可以了解下
    2021-04-04

最新評(píng)論

固阳县| 平潭县| 通州区| 安平县| 南江县| 北京市| 秭归县| 元江| 伊宁市| 博乐市| 铜陵市| 如皋市| 连州市| 延寿县| 昌吉市| 祁东县| 抚松县| 德化县| 长武县| 阿拉善右旗| 喀喇沁旗| 辽阳县| 本溪市| 南靖县| 饶阳县| 芒康县| 宿迁市| 大埔县| 饶阳县| 宁乡县| 田阳县| 汤原县| 陵水| 来宾市| 游戏| 阿拉善右旗| 三江| 蚌埠市| 太仆寺旗| 安宁市| 买车|