tdesign vue初始化組件源碼解析
前言
Tdesign-vue 是一由騰訊開源的 Vue.js 組件庫。我們知道,這些大型的組件庫業(yè)務(wù)覆蓋面很廣,基本都包含了很多組件,很多組件包含了一些通用性代碼,如果每開發(fā)一個(gè)組件,都去把這些通用性代碼復(fù)制出來,無疑是非常繁瑣的,那么作者在開發(fā)這些組件時(shí)是如何做的呢?
學(xué)習(xí)目標(biāo):
- 新增組件: npm run init [組件名]
- 刪除組件:npm run init [組件名] del
資源:
源碼地址:tdesign-vue/index.js
源碼
找到用于初始化組件的源碼,如圖:
腳本的入口
function init() { const [component, isDeleted] = process.argv.slice(2); if (!component) { console.error('[組件名]必填 - Please enter new component name'); process.exit(1); } const indexPath = path.resolve(cwdPath, 'src/index.ts'); const toBeCreatedFiles = config.getToBeCreatedFiles(component); if (isDeleted === 'del') { deleteComponent(toBeCreatedFiles, component); deleteComponentFromIndex(component, indexPath); } else { addComponent(toBeCreatedFiles, component); insertComponentToIndex(component, indexPath); } }
函數(shù)接受兩個(gè)參數(shù): Component 和 isDelete。
component
參數(shù)是要?jiǎng)?chuàng)建或刪除的組件的名稱isDelete
參數(shù)是一個(gè)標(biāo)志,指示是否應(yīng)該創(chuàng)建或刪除該組件。
函數(shù)首先檢查是否提供了組件參數(shù)。如果未提供,則向控制臺(tái)輸出一條錯(cuò)誤消息,函數(shù)退出。否則,函數(shù)將繼續(xù)執(zhí)行。
之后,該函數(shù)獲取需要?jiǎng)?chuàng)建或刪除的文件列表,以便添加或刪除組件。然后檢查 isDelete 參數(shù)的值,以確定是否應(yīng)該創(chuàng)建或刪除組件。如果 isDelete
等于 del
,則函數(shù)調(diào)用 deleteComponent
函數(shù)來刪除組件,然后調(diào)用 deleteComponentFromIndex
函數(shù)來從項(xiàng)目的索引文件中刪除組件。如果 isDelete
不等于 del
,則函數(shù)調(diào)用 addComponent
函數(shù)創(chuàng)建組件,然后調(diào)用 insertComponentToIndex
函數(shù)將組件添加到項(xiàng)目的索引文件中。
創(chuàng)建目錄
function addComponent(toBeCreatedFiles, component) { // At first, we need to create directories for components. Object.keys(toBeCreatedFiles).forEach((dir) => { const _d = path.resolve(cwdPath, dir); fs.mkdir(_d, { recursive: true }, (err) => { if (err) { utils.log(err, 'error'); return; } console.log(`${_d} directory has been created successfully!`); // Then, we create files for components. const contents = toBeCreatedFiles[dir]; contents.files.forEach((item) => { if (typeof item === 'object') { if (item.template) { outputFileWithTemplate(item, component, contents.desc, _d); } } else { const _f = path.resolve(_d, item); createFile(_f, '', contents.desc); } }); }); }); }
該函數(shù)接受兩個(gè)參數(shù): toBeCreatedFiles
和 component
。
toBeCreatedFiles
參數(shù)是一個(gè)對(duì)象,它包含為了添加組件而需要?jiǎng)?chuàng)建的目錄和文件的列表component
參數(shù)是要?jiǎng)?chuàng)建的組件的名稱。
函數(shù)首先迭代 toBeCreatedFiles
對(duì)象的鍵,這些鍵表示需要?jiǎng)?chuàng)建的目錄。對(duì)于每個(gè)目錄,該函數(shù)使用 fs.mkdir
函數(shù)創(chuàng)建目錄。如果目錄已經(jīng)存在,則函數(shù)將錯(cuò)誤消息記錄到控制臺(tái)。
創(chuàng)建目錄后,函數(shù)將遍歷需要為組件創(chuàng)建的文件列表。如果文件是包含模板屬性的對(duì)象,則函數(shù)調(diào)用 outputFileWithTemplate
函數(shù)以使用模板創(chuàng)建文件。如果文件不是具有模板屬性的對(duì)象,則函數(shù)調(diào)用 createFile 函數(shù)創(chuàng)建空文件。
內(nèi)容寫入
function insertComponentToIndex(component, indexPath) { const upper = getFirstLetterUpper(component); // last import line pattern const importPattern = /import.*?;(?=\n\n)/; // components pattern const cmpPattern = /(?<=const components = {\n)[.|\s|\S]*?(?=};\n)/g; const importPath = getImportStr(upper, component); const desc = '> insert component into index.ts'; let data = fs.readFileSync(indexPath).toString(); if (data.match(new RegExp(importPath))) { utils.log(`there is already ${component} in /src/index.ts`, 'notice'); return; } // insert component at last import and component lines. data = data.replace(importPattern, (a) => `${a}\n${importPath}`).replace(cmpPattern, (a) => `${a} ${upper},\n`); fs.writeFile(indexPath, data, (err) => { if (err) { utils.log(err, 'error'); } else { utils.log(`${desc}\n${component} has been inserted into /src/index.ts`, 'success'); } }); }
這個(gè)函數(shù)接受兩個(gè)參數(shù): component
和 indexPath
。
component
參數(shù)是要插入的組件的名稱indexPath
參數(shù)是項(xiàng)目索引文件的路徑。
該函數(shù)首先定義兩個(gè)正則表達(dá)式: importPattern
和 cmpPattern
。
importPattern
正則表達(dá)式用于匹配索引文件中的最后一個(gè)import
語句cmpPattern
正則表達(dá)式用于匹配索引文件中的組件列表。
接下來,函數(shù)使用 getImportStr
函數(shù),使用變量(組件名稱的大寫版本)為新組件生成導(dǎo)入語句。
然后,該函數(shù)使用 fs.readFileSync
函數(shù)讀取索引文件的內(nèi)容,并在文件中搜索 importPattern
和 cmpPattern
正則表達(dá)式。如果文件中已經(jīng)存在新組件的 import
語句,則函數(shù)將消息記錄到控制臺(tái)并返回。否則,該函數(shù)將最后一個(gè) import
語句替換為新 import
語句,并將組件列表替換為包含新組件的新組件列表。最后,函數(shù)使用 fs.writeFile
函數(shù)將修改后的索引文件內(nèi)容寫回文件。
刪除目錄
function deleteComponent(toBeCreatedFiles, component) { const snapShotFiles = getSnapshotFiles(component); const files = Object.assign(toBeCreatedFiles, snapShotFiles); Object.keys(files).forEach((dir) => { const item = files[dir]; if (item.deleteFiles && item.deleteFiles.length) { item.deleteFiles.forEach((f) => { fs.existsSync(f) && fs.unlinkSync(f); }); } else { utils.deleteFolderRecursive(dir); } }); utils.log('All radio files have been removed.', 'success'); }
該函數(shù)接受兩個(gè)參數(shù): toBeCreatedFiles 和 Component。
- toBeCreatedFiles 參數(shù)是一個(gè)包含與組件關(guān)聯(lián)的目錄和文件列表的對(duì)象
- component參數(shù)是要?jiǎng)h除的組件的名稱。
該函數(shù)首先調(diào)用 getSnapshoFiles 函數(shù)以獲取與組件關(guān)聯(lián)的快照文件列表。然后,它使用 Object.sign 函數(shù)將該列表與 toBeCreatedFiles 對(duì)象合并。
接下來,函數(shù)迭代合并對(duì)象的鍵,這些鍵表示需要?jiǎng)h除的目錄和文件。對(duì)于每個(gè)鍵,該函數(shù)檢查是否設(shè)置了關(guān)聯(lián)值的 deleteFiles 屬性。如果是,函數(shù)將遍歷文件列表并使用 fs.unlinkSync 函數(shù)刪除它們。如果未設(shè)置 deleteFiles 屬性,該函數(shù)將調(diào)用 deleteFolderRecursive 函數(shù)以刪除整個(gè)目錄及其所有內(nèi)容。
刪除導(dǎo)入語句
function deleteComponentFromIndex(component, indexPath) { const upper = getFirstLetterUpper(component); const importStr = `${getImportStr(upper, component)}\n`; let data = fs.readFileSync(indexPath).toString(); data = data.replace(new RegExp(importStr), () => '').replace(new RegExp(` ${upper},\n`), ''); fs.writeFile(indexPath, data, (err) => { if (err) { utils.log(err, 'error'); } else { utils.log(`${component} has been removed from /src/index.ts`, 'success'); } }); }
該函數(shù)接受兩個(gè)參數(shù): component 和 indexPath。
- component參數(shù)是要?jiǎng)h除的組件的名稱
- indexPath 參數(shù)是項(xiàng)目索引文件的路徑。
該函數(shù)首先使用 getImportStr 函數(shù),使用變量(組件名稱的大寫版本)為組件生成 import 語句。然后,它使用 fs.readFileSync 函數(shù)讀取索引文件的內(nèi)容,并在文件中搜索 import 語句和組件名。
如果找到 import 語句或組件名稱,函數(shù)將使用 String.place 函數(shù)將其替換為空字符串。最后,函數(shù)使用 fs.writeFile 函數(shù)將修改后的索引文件內(nèi)容寫回文件。如果在此過程中發(fā)生錯(cuò)誤,該函數(shù)將一條錯(cuò)誤消息記錄到控制臺(tái)。否則,它將記錄一條成功消息,指示組件已從索引文件中刪除。
總結(jié)
通過本次章節(jié)的學(xué)習(xí),學(xué)習(xí)到了動(dòng)態(tài)修改文件內(nèi)容以及根據(jù)模板生成組件文件的方式。
以上就是tdesign vue初始化組件源碼解析的詳細(xì)內(nèi)容,更多關(guān)于tdesign vue初始化組件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue樹形結(jié)構(gòu)數(shù)據(jù)處理的方法總結(jié)
在項(xiàng)目開發(fā)的過程中,會(huì)經(jīng)常使用樹形結(jié)構(gòu)數(shù)據(jù),前后端交互都會(huì)對(duì)數(shù)據(jù)進(jìn)行處理,后端返回的數(shù)據(jù)前端有的時(shí)候不能直接使用需要轉(zhuǎn)換,本文小編整理了一些項(xiàng)目中用到的處理方法,需要的朋友可以參考下2023-11-11vue項(xiàng)目開發(fā)中setTimeout等定時(shí)器的管理問題
這篇文章主要介紹了vue項(xiàng)目開發(fā)中setTimeout等定時(shí)器的管理問題,需要的朋友可以參考下2018-09-09vue數(shù)據(jù)傳遞--我有特殊的實(shí)現(xiàn)技巧
這篇文章主要介紹了vue數(shù)據(jù)傳遞一些特殊梳理技巧,需要的朋友可以參考下2018-03-03element tree懶加載:load="loadNode"只觸發(fā)一次的解決方案
本文主要介紹了element tree懶加載:load="loadNode"只觸發(fā)一次的解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08