VSCode中如何實現點擊DOM自動定位到相應代碼行
本文小編為大家詳細介紹“VSCode中如何實現點擊DOM自動定位到相應代碼行”,內容詳細,步驟清晰,細節處理妥當,希望這篇“VSCode中如何實現點擊DOM自動定位到相應代碼行”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
現在大型的 Vue項目基本上都是多人協作開發,并且隨著版本的迭代,Vue 項目中的組件數也會越來越多,如果此時讓你負責不熟悉的頁面功能開發,甚至你才剛剛加入這個項目,那么怎么樣才能快速找到相關組件在整個項目代碼中的文件位置呢?想必大家都有采取過以下這幾種方法:
【搜類名】,在工程文件里搜索頁面 DOM元素中的樣式類名
【找路由】,根據頁面鏈接找到Vue路由匹配的頁面組件
【找人】,找到當初負責開發該頁面的人詢問對應的代碼路徑
以上幾種方法確實能夠幫助我們找到具體的代碼文件路徑,但都需要人工去搜索,并不是很高效,那有沒有其它更高效的方式呢?
答案是有的。Vue官方就提供了一款 vue-devtools 插件,使用該插件就能自動在 VSCode 中打開對應頁面組件的源代碼文件
使用vue-devtools插件可以很好地提高我們查找對應頁面組件代碼的效率,但只能定位到對應的組件代碼,如果我們想要直接找到頁面上某個元素相關的具體代碼位置,還需要在當前組件源代碼中進行二次查找,并且每次都要先選擇組件,再點擊打開按鈕才能打開代碼文件,不是特別快捷。
針對這個問題,我們開發了輕量級的頁面元素代碼映射插件,使用該插件可以通過點擊頁面元素的方式,一鍵打開對應代碼源文件,并且精準定位對應代碼行,無需手動查找,能夠極大地提高開發效率和體驗。
二、實現原理
整個插件主要分為3個功能模塊:client、server、add-code-location,client端發送特定請求給server端,server端接收到該請求后執行定位代碼行命令,而add-code-location模塊用于源碼的轉換。
2.1 client
client端這里其實就是指瀏覽器,我們在點擊頁面元素時,瀏覽器就會發送一個特定請求給server端,該請求信息包含了具體的代碼文件路徑和對應代碼行號信息。
function?openEditor(filePath)?{ ??axios ????.get(`${protocol}//${host}:${port}/code`,?{ ??????params:?{ ????????filePath:?`${filePath}` ??????} ????}) ????.catch(error?=>?{ ??????console.log(error) ????}) }
而監聽頁面元素的點擊事件則通過事件代理的方式全局監聽,給document綁定了點擊事件,監聽鍵盤和鼠標點擊組合事件來發起定位代碼行請求,避免和頁面原生的click事件發生沖突。
function?openCode(e)?{ ??if?(isShiftKey?||?isMetaKey?||?e.metaKey?||?e.shiftKey)?{ ????e.preventDefault() ????const?filePath?=?getFilePath(e.target) ????openEditor(filePath) ??} ??... }
2.2 server
server端是指本地起的一個服務器,可以監聽client端發送的特定請求,當接收到執行定位命令的請求時,執行VSCode打開代碼文件命令,并定位到對應的代碼行。
2.2.1 webpack devServer
如果是采用webpack構建的項目,webpack的devServer開發服務器已經提供了一個before屬性,可以通過它來監聽發送給開發服務器的請求。
before:?function?(app)?{ ??app.get('/code',?function?(req,?res)?{ ????if?(req.query.filePath)?{ ??????//?執行vscode定位代碼行命令 ??????openCodeFile(req.query.filePath) ??????... ????} ????... ??}) }
2.2.2 vite configureServer
如果是采用Vite構建的項目,可以使用Vite插件來實現server端監聽特定請求,Vite插件擴展于rollup插件接口,并且在原有的基礎上增加了一些特有的鉤子函數,例如configureServer鉤子,通過該鉤子函數可以用于配置開發服務器來監聽特定的請求。
const?codeServer?=?()?=>?({ ??name:?'open-code-vite-server', ??configureServer(server)?{ ????server.middlewares.use((req,?res,?next)?=>?{ ??????... ??????if?(pathname?==?'/code')?{ ????????... ????????if?(filePath)?{ ??????????openCodeFile(filePath)?//?執行vscode定位代碼行命令 ??????????... ????????} ????????res.end() ??????} ??????... ????}) ??} })
2.2.3 執行 VSCode 定位命令
當server端監聽到client端發送的特定請求后,接下來就是執行VSCode定位代碼行命令。實際上,VSCode編輯器是可以通過code命令來啟動,并且可以相應使用一些命令行參數,例如:
"code --reuse-window"或"code -r"命令可以打開最后活動窗口的文件或文件夾;"code --goto"或"code -g"命令后面可以拼接具體文件路徑和行列號,當使用"code -g file:line:column"命令時可以打開某個文件并定位到具體的行列位置。
利用 VSCode 編輯器的這個特性,我們就能實現自動定位代碼行功能,對應的代碼路徑信息可以從client端發送的請求信息當中獲得,再借助node的child_process.exec方法來執行VSCode定位代碼行命令。
const?child_process?=?require('child_process') function?openCodeFile(path)?{ ??let?pathBefore?=?__dirname.substring(0,?__dirname.search('node_modules')) ??let?filePath?=?pathBefore?+?path ??child_process.exec(`code?-r?-g?${filePath}`) }
另外,為了正常使用 VSCode 的 Code命令,我們需要確保添加VSCode Code命令到環境變量當中。Mac系統用戶可以在VSCode界面使用command+shift+p快捷鍵,然后搜索Code 并選擇install 'code' command in path;Windows用戶可以找到VSCode安裝位置的bin文件夾目錄,并將該目錄添加到系統環境變量當中。
2.3 add-code-location
通過前面的介紹,大家應該了解了client端和server端的執行機制,并且在執行定位命令時需要獲取到頁面元素的代碼路徑,而具體的代碼路徑是以屬性的方式綁定到了DOM元素上,這時候就需要用到add-code-location模塊在編譯時轉換我們的源碼,并給 DOM元素添加對應的代碼路徑屬性。
2.3.1 獲取文件路徑
源碼轉換過程的第一步是獲取代碼文件的具體路徑,對于webpack打包的項目來說,webpack loader用來處理源碼字符串再合適不過,loader的上下文this對象包含一個resourcePath資源文件的路徑屬性,利用這個屬性我們很容易就能獲得每個代碼文件的具體路徑。
module.exports?=?function?(source)?{ ??const?{?resourcePath?}?=?this ??return?sourceCodeChange(source,?resourcePath) }
對于Vite構建的項目來說,源碼的轉化操作也是通過插件來完成,Vite插件有通用的鉤子transform,可用于轉換已加載的模塊內容,它接收兩個參數,code參數代表著源碼字符串,id參數是文件的全路徑。
module.exports?=?function()?{ ??return?{ ????name:?'add-code-location', ????transform(code,?id)?{ ??????... ??????return?sourceCodeChange(code,?id) ????} ??} }
2.3.2 計算代碼行號
接著在遍歷源碼文件的過程中,需要處理對應Vue文件template模板中的代碼,以“\n”分割template模板部分字符串為數組,通過數組的索引即可精準得到每一行html標簽的代碼行號。
function?codeLineTrack(str,?resourcePath)?{ ??let?lineList?=??str.split('\n') ??let?newList?=?[] ??lineList.forEach((item,?index)?=>?{ ????newList.push(addLineAttr(item,?index?+?1,?resourcePath))?//?添加位置屬性,index+1為具體的代碼行號 ??}) ??return?newList.join('\n') }
2.3.3 添加位置屬性
在獲取到代碼文件路徑和代碼行號以后,接下來就是對Vue template模板中分割的每一行標簽元素添加最終的位置屬性。這里采用的是正則替換的方式來添加位置屬性,分別對每一行標簽元素先正則匹配出所有元素的開始標簽部分,例如<div、<span、<img等,然后將其正則替換成帶有code-location屬性的開始標簽,對應的屬性值就是前面獲取的代碼路徑和對應標簽的行號。
function?addLineAttr(lineStr,?line,?resourcePath)?{ ??let?reg?=?/<[\w-]+/g ??let?leftTagList?=?lineStr.match(reg) ??if?(leftTagList)?{ ????leftTagList?=?Array.from(new?Set(leftTagList)) ????leftTagList.forEach(item?=>?{ ??????if?(item?&&?item.indexOf('template')?==?-1)?{ ????????let?regx?=?new?RegExp(`${item}`,?'g') ????????let?location?=?`${item}?code-location="${resourcePath}:${line}"` ????????lineStr?=?lineStr.replace(regx,?location) ??????} ????}) ??} ??return?lineStr }
2.4 其他處理
2.4.1 源碼相對路徑
在給DOM元素添加對應的源碼位置屬性時,實際上采用的是相對路徑,這樣可以使得DOM元素上的屬性值更加簡潔明了。node_modules文件夾通常是在項目的根目錄下,而插件是以npm包的形式安裝在node_modules路徑下,利用node的__dirname變量可以獲得當前模塊的絕對路徑,因此在源碼轉換過程中就可以獲取到項目的根路徑,從而就能獲得Vue代碼文件的相對路徑。
let?pathBefore?=?__dirname.substring(0,?__dirname.search('node_modules')) let?filePath?=?filePath.substring(pathBefore.length)?//?vue代碼相對路徑
在server端執行代碼定位命令時,再將對應的代碼相對路徑拼接成完整的絕對路徑。
2.4.2 外部引入組件
add-code-location雖然可以對本地的Vue文件進行代碼路徑信息的添加,但是對于外部引入或解析加載的組件目前是沒有辦法進行轉換的,例如element ui組件,實際上的代碼行信息只會添加在element ui組件的最外層。這時候client端在獲取點擊元素的代碼路徑時會做一個向上查找的處理,獲取其父節點的代碼路徑,如果還是沒有,會繼續查找父節點的父節點,直到成功獲取代碼路徑。
function?getFilePath(element)?{ ??if?(!element?||?!element.getAttribute)?return?null ??if?(element.getAttribute('code-location'))?{ ????return?element.getAttribute('code-location') ??} ??return?getFilePath(element.parentNode) }
這樣就可以在點擊后臺element ui搭建的頁面元素時,也能成功定位打開對應代碼文件。
三、接入方案
通過前面的介紹,想必大家對頁面元素代碼映射插件原理有了清晰的了解,接下來就介紹一下在項目中的接入方式。接入方式其實很簡單,并且可以選擇只在本地開發環境接入,不用擔心對我們的生產環境造成影響,放心使用。
3.1 webpcak構建項目
對于webpack構建的項目來說,首先在構建配置項vue.config.js文件中配置一下devServer和webpack loader,接著在main.js入口文件中初始化插件。
//?vue.config.js const?openCodeServe?=?require('@vivo/vue-dev-code-link/server') devServer:?{ ??... ??before:?openCodeServe.before }, ? if?(!isProd)?{?//?本地開發環境 ??config.module ????.rule('vue') ????.test(/\.vue/) ????.use('@vivo/vue-dev-code-link/add-location-loader') ????.loader('@vivo/vue-dev-code-link/add-location-loader') ????.end() } //?main.js import?openCodeClient?from?'@vivo/vue-dev-code-link/client' if?(process.env.NODE_ENV?==?'development')?{ ??openCodeClient.init() }
3.2 Vite構建項目
Vite構建項目接入該插件的方案和webpack構建項目基本上一致,唯一不一樣的地方在于打包配置文件里引入的是兩個Vite插件。
//?vite.config.js import?openCodeServer?from?'@vivo/vue-dev-code-link/vite/server' import?addCodeLocation?from?'@vivo/vue-dev-code-link/vite/add-location' export?default?defineConfig({ ??plugins:?[ ????openCodeServer(), ????addCodeLocation() ??] }
讀到這里,這篇“VSCode中如何實現點擊DOM自動定位到相應代碼行”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注蝸牛博客行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:niceseo99@gmail.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。
評論