日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

小姐姐笔记:我是如何学习简单源码拓展视野的

發(fā)布時(shí)間:2023/12/9 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 小姐姐笔记:我是如何学习简单源码拓展视野的 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

大家好,我是若川。這是我上周組織的源碼共讀紀(jì)年小姐姐的筆記,寫得很好。所以分享給大家。歡迎加我微信 ruochuan12,進(jìn)源碼共讀群。其他更多人的筆記可以閱讀原文查看。


川哥的源碼解讀文章:據(jù)說(shuō) 99% 的人不知道 vue-devtools 還能直接打開(kāi)對(duì)應(yīng)組件文件?本文原理揭秘

???? 非常感謝川哥組織的源碼閱讀活動(dòng)

1. 解讀前的準(zhǔn)備

1.1 粗略閱讀一遍川哥的源碼解讀文章,弄清楚文章的主旨內(nèi)容:探究 vue-devtools「在編輯器中打開(kāi)組件」功能實(shí)現(xiàn)原理**,它的核心實(shí)現(xiàn)就是 launch-editor**。

1.2 明確自己到底要學(xué)習(xí)什么:

1)學(xué)習(xí)調(diào)試源碼的方法;

2)在調(diào)試過(guò)程中探究 launch-editor 源碼是如何實(shí)現(xiàn)在編輯器打開(kāi)對(duì)應(yīng)的文件;

目標(biāo):跟著川哥的文章完整走完一遍調(diào)試的流程,并對(duì)外輸出記錄文檔。

1.3 資源:

  • 下載川哥的源碼:git clone https://github.com/lxchuan12/open-in-editor.git,進(jìn)入 vue3-project 目錄,安裝依賴yarn install

  • 安裝 vue-devtools 谷歌擴(kuò)展:翻墻去應(yīng)用商店下載安裝即可(下載 6.0.0 beta 版)

  • 了解 launch-editor[1]:主要功能是在編輯器中打開(kāi)帶有行號(hào)的文件

2. 開(kāi)始學(xué)習(xí),淺嘗輒止

上述的準(zhǔn)備工作搞完之后,我們動(dòng)手操作一下。

2.1 開(kāi)始動(dòng)手

我使用的編輯器是 VSCode。

打開(kāi) vue3-project 目錄的 package.json,點(diǎn)擊調(diào)試,選擇 serve。這一步操作,使得我們以 debug 的形式,運(yùn)行了 vue-cli-service serve 這個(gè)命令。

img

跟著文章實(shí)現(xiàn)到這里的時(shí)候,我有點(diǎn)懵逼,因?yàn)槲也恢澜酉聛?lái)為什么突然要搜索【launch-editor-middleware】這個(gè)庫(kù)。

直到我再次通讀一遍文章,發(fā)現(xiàn)川哥前面有提到 vue-devtools 的 Open component in editor[2] 這個(gè)文檔,這個(gè)文檔里面描述了引用了【launch-editor-middleware】這個(gè)庫(kù)來(lái)實(shí)現(xiàn)打開(kāi)文檔的功能。而我之前先入為主地以為,這期是解讀 vue-devtools 的源碼,其實(shí)這只是解讀實(shí)現(xiàn)打開(kāi)文檔功能的源碼而已。

理解了這一層,我們可以直接搜項(xiàng)目里(包括 node_modules)里的【launch-editor-middleware】關(guān)鍵字,就可以找到這個(gè)庫(kù)的源碼位置了。

2.2 調(diào)試之旅

調(diào)試的流程就是打斷點(diǎn),點(diǎn)擊調(diào)試的流程面板,經(jīng)過(guò)不斷調(diào)試,觀察數(shù)據(jù)的變化。

下圖【launch-editor-middleware】的源碼,在這份源碼中我們能很輕易地分析出,最終運(yùn)行的是 launch 函數(shù),我們可以這這里打一個(gè)斷點(diǎn),然后進(jìn)入到【launch-editor】的源碼,實(shí)際運(yùn)行的是 launchEditor 函數(shù)。

imgimg

粗略看一遍 launchEditor 函數(shù),發(fā)現(xiàn)它實(shí)際上是做了四件事:

  • 獲取 fileName,lineNumber,columnNumber

  • 異常處理:是否存在文件,onErrorCallback,是否存在 editor

  • 猜測(cè)當(dāng)前正在使用的編輯器:guessEditor

  • 使用 child_process.spwan 異步打開(kāi)一個(gè)子進(jìn)程模塊,它調(diào)起了 cmd.exe 工具打開(kāi)我們的編輯器,并打開(kāi)了文件(args 就是文件的參數(shù))

看完了這個(gè)函數(shù),其實(shí)大概實(shí)現(xiàn)的原理也就出來(lái)了,核心代碼如下:

if?(process.platform?===?'win32')?{_childProcess?=?childProcess.spawn('cmd.exe',['/C',?editor].concat(args),{?stdio:?'inherit'?}) }?else?{_childProcess?=?childProcess.spawn(editor,?args,?{?stdio:?'inherit'?}) }

但我們肯定還有很多疑惑,比如:

  • 在瀏覽器控制臺(tái)點(diǎn)擊按鈕,編輯器是怎么接收到它的請(qǐng)求信息呢?

  • 用到了哪些 API/編程技巧?

  • 這個(gè)功能實(shí)現(xiàn)如果讓我們來(lái)實(shí)現(xiàn),是怎么實(shí)現(xiàn)呢(復(fù)述思路)?

3. 動(dòng)手操作,深入實(shí)踐

在前面的拆解中,雖然很多地方看似看懂了,但又沒(méi)完全懂,那我們來(lái)解答一下在看源碼的時(shí)候的疑問(wèn):

3.1 編輯器如何接收到瀏覽器的請(qǐng)求信息

點(diǎn)擊 vue-devtools 的按鈕時(shí),我們會(huì)發(fā)現(xiàn)它發(fā)送了一個(gè)請(qǐng)求:http://localhost:8080/__open-in-editor?file=src/components/HelloWorld.vue

img

那編輯器是如何接收到這個(gè)請(qǐng)求呢?搜索【launch-editor-middleware】關(guān)鍵字,我們會(huì)發(fā)現(xiàn),在 @vue/cli-service 的 serve.js 文件中,使用了 app.use("/__open-in-editor"),用過(guò) express 的小伙伴會(huì)比較熟悉,這是express 引入中間件的用法。當(dāng)瀏覽器發(fā)送 http://localhost:8080/__open-in-editor?file=src/components/HelloWorld.vue 這個(gè)請(qǐng)求的時(shí)候,就進(jìn)入到下面這個(gè)代碼了。

//?vue3-project/node_modules/@vue/cli-service/lib/commands/serve.js //?46行 const?launchEditorMiddleware?=?require('launch-editor-middleware') //?192行 before?(app,?server)?{//?launch?editor?support.//?this?works?with?vue-devtools?&?@vue/cli-overlayapp.use('/__open-in-editor',?launchEditorMiddleware(()?=>?console.log(`To?specify?an?editor,?specify?the?EDITOR?env?variable?or?`?+`add?"editor"?field?to?your?Vue?project?config.\n`)))//?省略若干代碼... }

3.2 用到了哪些 API/編程技巧

3.2.1 函數(shù)的重載

在【launch-editor-middleware】的入口函數(shù)這里,使用了函數(shù)重載的寫法,這種寫法在很多源碼中都很常見(jiàn),目的是方便用戶調(diào)用時(shí)傳參,針對(duì)不定量的參數(shù)對(duì)應(yīng)不同的操作內(nèi)容。

//?vue3-project/node_modules/launch-editor-middleware/index.js const?url?=?require('url') const?path?=?require('path') const?launch?=?require('launch-editor')module.exports?=?(specifiedEditor,?srcRoot,?onErrorCallback)?=>?{//?specifiedEditor?=>?這里傳遞過(guò)來(lái)的則是?()?=>?console.log()?函數(shù)//?所以和?onErrorCallback?切換下,把它賦值給錯(cuò)誤回調(diào)函數(shù)if?(typeof?specifiedEditor?===?'function')?{onErrorCallback?=?specifiedEditorspecifiedEditor?=?undefined}//?如果第二個(gè)參數(shù)是函數(shù),同樣把它賦值給錯(cuò)誤回調(diào)函數(shù)//?這里傳遞過(guò)來(lái)的是undefinedif?(typeof?srcRoot?===?'function')?{onErrorCallback?=?srcRootsrcRoot?=?undefined}//?srcRoot?是傳遞過(guò)來(lái)的參數(shù),或者當(dāng)前?node?進(jìn)程的目錄srcRoot?=?srcRoot?||?process.cwd()//?最后返回一個(gè)函數(shù),?express?中間件return?function?launchEditorMiddleware?(req,?res,?next)?{//?省略?...} }

3.2.2 裝飾器模式

這段代碼 wrapErrorCallback 先執(zhí)行其他代碼,再去執(zhí)行 onErrorCallback,這種包裹函數(shù)的形式在很多源碼里都也很常見(jiàn),可以理解為一個(gè)裝飾器,把 onErrorCallback 包裝了起來(lái),對(duì)原函數(shù)進(jìn)行了增強(qiáng)。

這也是設(shè)計(jì)模式中的裝飾器設(shè)計(jì)模式:

function?wrapErrorCallback?(cb)?{return?(fileName,?errorMessage)?=>?{console.log()console.log(chalk.red('Could?not?open?'?+?path.basename(fileName)?+?'?in?the?editor.'))if?(errorMessage)?{if?(errorMessage[errorMessage.length?-?1]?!==?'.')?{errorMessage?+=?'.'}console.log(chalk.red('The?editor?process?exited?with?an?error:?'?+?errorMessage))}console.log()if?(cb)?cb(fileName,?errorMessage)} }onErrorCallback?=?wrapErrorCallback(onErrorCallback)

3.2.3 apply

apply 語(yǔ)法:func.apply(thisArg, [argsArray]),也經(jīng)常在源碼中可以看到。這里使用 apply 是把 extraArgs 作為 push 方法的 arguments 傳進(jìn)去。

if?(lineNumber)?{//?getArgumentsForPosition?返回一個(gè)數(shù)組const?extraArgs?=?getArgumentsForPosition(editor,?fileName,?lineNumber,?columnNumber)//?將?extraArgs?參數(shù)?push?到?args?里args.push.apply(args,?extraArgs) }?else?{args.push(fileName) }

3.2.4 child_process

child_process 是 Node.js 的一個(gè)模塊,它提供了衍生子進(jìn)程的能力,默認(rèn)情況下,會(huì)在父 Node.js 進(jìn)程和衍生的子進(jìn)程之間建立 stdin、stdout 和 stderr 的管道。

3.2.5 process.platform

用于標(biāo)識(shí)運(yùn)行 Node.js 進(jìn)程的操作系統(tǒng)平臺(tái),返回字符串,目前可能的值有:?"aix" | "darwin" | "freebsd" | "linux" | "openbsd" | "sunos" | "win32"

3.3 如何實(shí)現(xiàn)(復(fù)述思路)

  • 瀏覽器與編輯器的通訊:借助 Node.js 進(jìn)程,與瀏覽器發(fā)生通訊

  • 瀏覽器將需要打開(kāi)的文件路徑通過(guò)參數(shù)傳遞給編輯器

  • 判斷操作系統(tǒng)平臺(tái)和所使用的編輯器(每個(gè)平臺(tái)的命令行程序不一樣,每個(gè)編輯器的環(huán)境變量也不一樣)

  • 借助 Node 調(diào)起 cmd.exe 工具打開(kāi)我們的編輯器,打開(kāi)對(duì)應(yīng)路徑的文件

//?偽代碼 app.use("__open-in-editor",?handleLaunchEditor)function?handleLaunchEditor(filePath)?{const?platform?=?process.platformconst?editor?=?guessEditor()childProcess.spawn(editor,?fileArgs,?{?stdio:?'inherit'?}) }

4. 感想

  • 編碼能力:通過(guò)解讀 launch-editor 源碼,學(xué)習(xí)/重溫了【函數(shù)的重載】【裝飾器模式】【apply 使用方法】,源碼的組織結(jié)構(gòu)也非常值得我們學(xué)習(xí),比如里面很多功能代碼都單獨(dú)封裝起來(lái),封裝成函數(shù)或者模塊,使得整個(gè)源碼的結(jié)構(gòu)非常清晰,核心通俗易懂,易于解讀和維護(hù)。(這也可以理解為自頂向下的編程方法)

  • 拓展視野:源碼中包含了很多與 Node.js 相關(guān)的方法,有很多都是我不熟悉的,在解讀源碼的過(guò)程也是我學(xué)習(xí) Node.js 的過(guò)程。

  • 工作中可能會(huì)用到:

    • 開(kāi)發(fā) VSCode 插件與外界通訊可借助 Node.js 進(jìn)程

    • 裝飾器模式的應(yīng)用

    • 判斷操作系統(tǒng)平臺(tái)

參考資料

[1]

launch-editor: https://github.com/yyx990803/launch-editor

[2]

Open component in editor: https://github.com/vuejs/devtools/blob/legacy/docs/open-in-editor.md


最近組建了一個(gè)江西人的前端交流群,如果你是江西人可以加我微信?ruochuan12?私信 江西?拉你進(jìn)群。


推薦閱讀

我在阿里招前端,該怎么幫你(可進(jìn)面試群)
我讀源碼的經(jīng)歷

面對(duì) this 指向丟失,尤雨溪在 Vuex 源碼中是怎么處理的
老姚淺談:怎么學(xué)JavaScript?

·················?若川簡(jiǎn)介?·················

你好,我是若川,畢業(yè)于江西高校。現(xiàn)在是一名前端開(kāi)發(fā)“工程師”。寫有《學(xué)習(xí)源碼整體架構(gòu)系列》多篇,在知乎、掘金收獲超百萬(wàn)閱讀。
從2014年起,每年都會(huì)寫一篇年度總結(jié),已經(jīng)寫了7篇,點(diǎn)擊查看年度總結(jié)。
同時(shí),活躍在知乎@若川,掘金@若川。致力于分享前端開(kāi)發(fā)經(jīng)驗(yàn),愿景:幫助5年內(nèi)前端人走向前列。

識(shí)別方二維碼加我微信、拉你進(jìn)源碼共讀

今日話題

略。歡迎分享、收藏、點(diǎn)贊、在看我的公眾號(hào)文章~

總結(jié)

以上是生活随笔為你收集整理的小姐姐笔记:我是如何学习简单源码拓展视野的的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。