欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue3 編譯流程-源碼解析

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

前言:

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

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

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

我個人是不太喜歡在看源碼分析文章時一上來就懟出一大段代碼,這容易讓沒閱讀的同學有點懵逼。所以這個系列的文章我會盡量對關鍵的代碼畫出一張流程圖。目的還是一個,幫助大家降低理解成本,同時也讓各位同學在下次自主閱讀時有張流程圖能參考。

1、解讀Vue 入口文件

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

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

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

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

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

這個簡單的模板,在經(jīng)過編譯后,code 返回的字符串為

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

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

在拿到這個這個代碼字符串的結果后,我們再順著代碼往下看,第 25 行聲明了一個 render 變量,并且將生成的代碼字符串 code 作為參數(shù)傳入了 new Function 構造函數(shù)。這就是流程圖中的倒數(shù)第二步,生成了 render 函數(shù)。可以將我放在上面的 code 字符串格式化,能夠發(fā)現(xiàn) render 函數(shù)是一個柯里化的函數(shù),返回了一個函數(shù),函數(shù)內(nèi)部通過 with 來擴展作用域鏈。

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

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

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

 2、compile 的運行流程

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

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

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

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

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

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

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

接下來源碼是 16 行調用了 transform 函數(shù),以及傳入了指令轉換、節(jié)點轉換等工具函數(shù),對由模板生成的 AST 進行轉換。

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

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

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

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

相關文章

  • Vue3新特性Suspense和Teleport應用場景分析

    Vue3新特性Suspense和Teleport應用場景分析

    本文介紹了Vue2和Vue3中的Suspense用于處理異步請求的加載提示,以及如何在組件間實現(xiàn)動態(tài)加載,同時,Teleport技術展示了如何在DOM中靈活地控制組件的渲染位置,解決布局問題,感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • 啟動myvue報錯npm?ERR!?code?ENOENT?npm?ERR!?syscall?open的解決辦法

    啟動myvue報錯npm?ERR!?code?ENOENT?npm?ERR!?syscall?open的解

    這篇文章主要介紹了啟動myvue報錯npm?ERR!?code?ENOENT?npm?ERR!?syscall?open的解決辦法,文中給出了詳細的解決方法,并通過圖文結合的方式介紹的非常詳細,需要的朋友可以參考下
    2024-03-03
  • Vue+Element UI 實現(xiàn)視頻上傳功能

    Vue+Element UI 實現(xiàn)視頻上傳功能

    這篇文章主要介紹了Vue+Element UI 實現(xiàn)視頻上傳功能,前臺使用Vue+Element UI中的el-upload組件實現(xiàn)視頻上傳及進度條展示,后臺提供視頻上傳API并返回URL,具體實現(xiàn)代碼及效果展示跟隨小編一起看看吧
    2022-01-01
  • Vue infinite update loop的問題解決

    Vue infinite update loop的問題解決

    這篇文章主要介紹了Vue "...infinite update loop..."的問題解決,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-04-04
  • vue data有值,但是頁面{{}} 取不到值的解決

    vue data有值,但是頁面{{}} 取不到值的解決

    這篇文章主要介紹了vue data有值,但是頁面{{}} 取不到值的解決,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • vue3如何實現(xiàn)掛載并使用axios

    vue3如何實現(xiàn)掛載并使用axios

    這篇文章主要介紹了vue3如何實現(xiàn)掛載并使用axios,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 關于elementUi表格合并行數(shù)據(jù)并展示序號

    關于elementUi表格合并行數(shù)據(jù)并展示序號

    這篇文章主要介紹了關于elementUi表格合并行數(shù)據(jù)并展示序號,通過給table傳入span-method方法可以實現(xiàn)合并行或列,方法的參數(shù)是一個對象,感興趣的朋友可以學習一下
    2023-04-04
  • 詳解Vue中CSS樣式穿透問題

    詳解Vue中CSS樣式穿透問題

    這篇文章主要介紹了VUE中CSS樣式穿透問題,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-09-09
  • Vue組件之間的通信你知道多少

    Vue組件之間的通信你知道多少

    這篇文章主要為大家詳細介紹了Vue組件之間的通信,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • Element-UI中Upload上傳文件前端緩存處理示例

    Element-UI中Upload上傳文件前端緩存處理示例

    這篇文章主要介紹了Element-UI中Upload上傳文件前端緩存處理示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-02-02

最新評論