- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) > web開(kāi)發(fā) > JavaScript >
- 解析如何自動(dòng)化生成vue組件文檔
Vue框架在前端開(kāi)發(fā)中應用廣泛,當一個(gè)多人開(kāi)發(fā)的Vue項目經(jīng)過(guò)長(cháng)期維護之后往往會(huì )沉淀出很多的公共組件,這個(gè)時(shí)候經(jīng)常會(huì )出現一個(gè)人 開(kāi)發(fā)了一個(gè)組件而其他維護者或新接手的人卻不知道這個(gè)組件是做什么的、該怎么用,還必須得再去翻看源碼,或者壓根就沒(méi)注意到這個(gè)組件 的存在導致重復開(kāi)發(fā)。這個(gè)時(shí)候就非常需要維護對應的組件文檔來(lái)保障不同開(kāi)發(fā)者之間良好的協(xié)作關(guān)系了。
但是傳統的手動(dòng)維護文檔又會(huì )帶來(lái)新問(wèn)題:
而理想中的文檔維護方式則是:
為了能實(shí)現上述理想效果,我搜索并研究了一下社區中的解決方案,目前Vue官方提供了Vue-press可以用于快速搭建Vue項目文檔, 而且也已經(jīng)有了可以自動(dòng)從Vue組件中提取信息的庫了。
但是已有的第三方庫并不能完全滿(mǎn)足需求,主要存在以下兩個(gè)問(wèn)題:
有較多的自定義標識,而且標識的命名過(guò)于個(gè)性化,對原有的代碼侵入還是比較大的。例如下圖中的代碼,為了標記注釋?zhuān)枰谠械?業(yè)務(wù)代碼中額外添加"@vuese" "@arg"等標識,使得業(yè)務(wù)代碼多出了一些業(yè)務(wù)無(wú)關(guān)內容。
針對以上文中提到的問(wèn)題以及社區方案的不足,我們團隊內沉淀出了一個(gè)小工具專(zhuān)門(mén)用于Vue組件信息獲取并輸出組件文檔,大致效果如下:
上圖中左邊是一個(gè)常見(jiàn)的Vue單文件組件,右邊是生成的文檔。我們可以看到我們從組件中成功的提取到了以下一些信息:
接下來(lái)我們將詳細的講解如何從組件中提取這些信息。
既然是要從Vue組件中提取信息,那么首先的問(wèn)題就是如何解析Vue組件。Vue官方開(kāi)發(fā)了Vue-template-compiler庫專(zhuān)門(mén)用于Vue解析, 這里我們也可以用同樣的方式來(lái)處理。通過(guò)查閱文檔可知Vue-template-compiler提供了一個(gè)parseComponent方法可以對原始的Vue文件進(jìn)行處理。
import { parseComponent } from 'Vue-template-compiler' const result = parseComponent(VueFileContent, [options])
處理后的結果如下,其中template和script分別對應Vue文件中的template和script的文本內容。
export interface SFCDescriptor { template: SFCBlock | undefined; script: SFCBlock | undefined; styles: SFCBlock[]; customBlocks: SFCBlock[]; }
當然僅僅是得到文本是不夠的,還需要對文本進(jìn)行更進(jìn)一步的處理來(lái)獲取更多的信息。得到script后,我們可以用babel把js編譯成js的AST(抽象語(yǔ)法樹(shù)),這個(gè)AST是一個(gè)普通的js對象,可以通過(guò)js進(jìn)行遍歷和讀取 有了Ast之后我們就可以從中獲取到我們想到詳細的組件信息了。
import { parse } from '@babel/parser'; const jsAst = parse(script, [options]);
接著(zhù)我們來(lái)看template,繼續查找Vue-template-compiler的文檔我們找到compile方法,compile是專(zhuān)門(mén)用于將template編譯成AST的, 正好可以滿(mǎn)足需求。
import { compile } from 'Vue-template-compiler' const templateAst = compile(template, [options]);
得到結果中的ast則為template的編譯結果。
export interface CompiledResult { ast: ASTElement, render: string, staticRenderFns: Array<string>, errors: Array<string> }
通過(guò)第一步的文件解析工作,我們成功獲取到了Vue的模板ast和script中的js的AST,下一步我們就可以從中獲取我們想要的信息了。
根據是否需要約定,信息可以分為兩種:
為了方便的從ast中讀取信息,這里先簡(jiǎn)單介紹一個(gè)工具@babel/traverse,這個(gè)庫是babel官方提供的專(zhuān)門(mén)用于遍歷js AST的。使用方式如下;
import traverse from '@babel/traverse' traverse(jsAst, options);
通過(guò)在options中配置對應內容的回調函數,可以獲得想要的ast節點(diǎn)。具體的使用可以參考
可以從代碼中直接獲取的信息可以有效的解決信息同步問(wèn)題,無(wú)論代碼怎么變動(dòng),文檔的關(guān)鍵信息都可以自動(dòng)同步,省去了人工校對的麻煩。
可以直接獲取的信息有:
1、2都可以利用traverse在js AST上直接遍歷名稱(chēng)為props和methods的對象節點(diǎn)獲取。
事件的獲取稍微麻煩一點(diǎn),可以通過(guò)查找$emit函數來(lái)定位到事件的位置,而$emit函數可以在traverse中監聽(tīng)MemberExpress(復雜類(lèi)型節點(diǎn)), 然后通過(guò)節點(diǎn)上的屬性名是否是'$emit'判斷是否是事件。如果是事件,那么在$emit父級中讀取arguments字段, arguments的第一個(gè)元素就是事件名稱(chēng),后面的元素為事件傳參。
this.$emit('event', arg);
traverse(jsAst, { MemberExpression(Node) { // 判斷是不是event if (Node.node.property.name === '$emit') { // 第一個(gè)元素是事件名稱(chēng) const eventName = Node.parent.arguments[0]; } } });
在成功獲取到Events后,那么結合Events和props,就可以進(jìn)一步的判斷出props中的兩個(gè)特殊屬性:
插槽slots的信息保存在上文的template的AST中,遞歸遍歷template AST找到名為slots的節點(diǎn),進(jìn)而還可以在節點(diǎn)上查找到name。
為什么除了可直接獲取的組件信息之外,還會(huì )需要額外的約定一部分內容呢?其一是因為可直接獲取的信息內容比較單薄,還不足以支撐起一個(gè)相對完善的組件文檔;其二是我們日常開(kāi)發(fā)組件時(shí)本身就會(huì )寫(xiě)很多的注釋?zhuān)绻苤苯訉⒉糠肿⑨屘崛〕鰜?lái)放到文檔中,可以大大降低文檔維護的工作量;
整理一下可以約定的內容有以下幾條:
接下來(lái)我們著(zhù)重講解如何將提取注釋和注釋與被注釋的內容是如何對應起來(lái)的。
js中的注釋根據位置不同可以分為頭部注釋(leadingComments)和尾部注釋(trailingComments),不同位置的注釋會(huì )存放在對應的字段中, 代碼展示如下:
// 頭部注釋export default {} // 尾部注釋
解析結果
const exportNode = { type: "ExportDefaultDeclaration", leadingComments: [{ type: 'CommentLine', value: '頭部注釋' }], trailingComments: [{ type: 'CommentLine', value: '尾部注釋' }] }
在同一個(gè)位置上,根據注釋格式的不同又分為單行注釋(CommentLine)和塊級注釋(CommentBlock),兩種注釋的區別會(huì )反應在注釋節點(diǎn)的type字段中:
/** * 塊級注釋 */ // 單行注釋 export default {}
解析結果
const exportNode = { type: "ExportDefaultDeclaration", leadingComments: [ { type: 'CommentBlock', value: '塊級注釋' }, { type: 'CommentLine', value: '單行注釋' } ] }
另外,從上面的解析結果我們也可以看到,注釋節點(diǎn)是掛載在被注釋的export節點(diǎn)里面的,這也解決我們上面提到的另一個(gè)問(wèn)題:注釋與被注釋的關(guān)聯(lián)關(guān)系怎么獲取的--其實(shí)babel在編譯代碼的時(shí)候已經(jīng)替我們做好了。
template查找注釋與被注釋內容的方法不同。template中注釋節點(diǎn)與其他節點(diǎn)一樣是作為dom節點(diǎn)存在的, 在遍歷節點(diǎn)的時(shí)候通過(guò)判斷isComment字段的值是否為true來(lái)確定是否是注釋節點(diǎn)。而被注釋的內容的位置在兄弟節點(diǎn)的后一位:
<!--template的注釋--> <slot>被注釋的節點(diǎn)</slot>
解析結果
const templateAst = [ { isComment: true, text: "template的注釋", type: 3 }, { tag: "slot", type: 1 } ]
知道了如何處理注釋內容,那么我們還可以利用注釋做更多的事情。例如可以通過(guò)在methods的方法的注釋中約定一個(gè)標記@public來(lái)區分是私有方法還是公共方法,如果更細節一點(diǎn)的話(huà), 還可以參考另一個(gè)專(zhuān)門(mén)用于解析js注釋的庫js-doc的格式,對方法的入參進(jìn)行更進(jìn)一步的說(shuō)明,豐富文檔的內容。
我們只需要在獲取到注釋內容之后對文本進(jìn)行切割讀取即可,例如:
export default { methods: { /** * @public * @param {boolean} value 入參說(shuō)明 */ show(value) {} } }
當然了為了避免對代碼侵入過(guò)多,我們還是需要盡量少的添加額外的標識。而入參說(shuō)明采用了與js-doc相同的格式,主要還是因為這套方案 使用比較普遍,而且代碼編輯器都自動(dòng)支持方便編輯。
編寫(xiě)組件文檔是一個(gè)可以很好的提升項目?jì)雀鱾€(gè)前端開(kāi)發(fā)成員之間協(xié)作的事情,一份維護良好的文檔會(huì )極大的改善開(kāi)發(fā)體驗。而如果能進(jìn)一步的使用工具把維護文檔的過(guò)程自動(dòng)化的話(huà),那開(kāi)發(fā)的幸福感還能得到再次提升。
經(jīng)過(guò)一系列的摸索和嘗試,我們成功的找到了 自動(dòng)化提取Vue組件信息的方案,大大減輕了維護Vue組件文檔的工作量,提升了文檔信息的準確度。具體實(shí)現上,先用vue-template-compiler對Vue文件進(jìn)行處理,獲得template的AST和js的AST,有了這兩個(gè)AST后就可以去獲取更加詳細的信息了, 梳理一下到目前為止我們生成的文檔里可以獲取到的內容及獲取方式:
至于獲取到內容之后是以Markdown的形式輸出還是json文件的形式輸出,就取決于實(shí)際的開(kāi)發(fā)情況了。
這里我們所討論的是直接從單個(gè)Vue文件去獲取信息并輸出,但是像很多第三方組件庫里例如elementUI的文檔,不僅有組件信息還有展示實(shí)例。如果一個(gè)組件庫維護的相對完善的話(huà),一個(gè)組件應該會(huì )有對應的測試用例,那么是否可以將組件的測試用例也提取出來(lái), 實(shí)現組件文件中示例部分的自動(dòng)提取呢?這也是值得研究的問(wèn)題。
以上就是解析如何自動(dòng)化生成vue組件文檔的詳細內容,更多關(guān)于自動(dòng)化生成vue組件文檔的資料請關(guān)注腳本之家其它相關(guān)文章!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站