打造自己的vue文檔生成工具


程序員最討厭的兩件事情,第一種是寫文檔,另一種是別人沒有寫文檔。有沒有直接根據vue組件生成文檔的呢?當然是有的的。但第三方使用起來不一定能和現有項目結合使用,往往需要額外的注釋用來標記提取信息。使用第三方的一些比較常見問題

  • 文檔提取信息不全面,可能有些信息你需要提取但是它又不支持。這種情況下就只能修改三方的插件源碼了。
  • 需要額為的注釋信息來標記,例如 vuese 需要給方法 打 @vuese@arg 等標記來提供方法信息。

俗話說自己動手豐衣足食,打造自己的vue文檔生成工具與自己項目結合使用。一個組件文檔大致需要提供 組件名稱和描述(name)組件屬性(props)組件方法(methods)組件事件(event)插槽(slot) 這幾個部分,以及還需要這個幾個部分的注釋組成生成描述信息。接下來一步步實現對着幾個部分的提取實現。

解析.vue 文件

一般一個.vue文件分三個部分 templatescriptstylestyle部分的內容我們不需要,我們需要分別提取出 template 和 script 內容。Vue官方開發了 Vue-template-compiler 庫專門用於Vue解析,我們可以直接使用它來解析提取.vue文件, Vue-template-compiler 提供了一個 parseComponent 方法可以對原始的Vue文件進行處理。

const compiler = require('vue-template-compiler')
const result = compiler.parseComponent(vueStr, [options])

// parseComponent 返回 template、script、style內容,
export interface SFCDescriptor {
template: SFCBlock | undefined;
script: SFCBlock | undefined;
styles: SFCBlock[];
customBlocks: SFCBlock[];
}

拿到各個部分文本后,還需要將它轉成ast(抽象語法樹),template 部分內容可以直接使用 Vue-template-compiler 提供的 compile 方法直接生成ast, script部分需要借助其他的生成ast了,這里使用 babel 的模塊來處理 js 文本。

const compiler = require('vue-template-compiler')
//vueStr .vue 文件內容
const vue = compiler.parseComponent(vueStr)

//生成html部分的 ast
let template = compiler.compile(vue.template.content, {
preserveWhitespace: false,
comments: true // 生成注釋信息
})

使用 @babel/parser(Babel解析器,是Babel中使用的JavaScript解析器)來處理js 文本內容。

const parse = require('@babel/parser');

//生成js部分的 ast
let jsAst = parse.parse(vue.script.content, {
allowImportExportEverywhere: true
})

 

提取文檔信息

通過上一步的文件解析工作,我們成功獲取到了Vue的模板ast和script中的js的ast,下一步我們就可以從中獲取我們想要的信息了這里需要使用到 @babel/traverse 這個工具,用來遍歷 js ast 的節點工具。可以在這里查看 ast 的生成內容,方便查看各種節點信息。

const traverse = require('@babel/traverse');
traverse.default(jsAst, {
enter(path){ // 開始

},
// 支持自定義節點 比如當節點類型 為 ExportDefaultDeclaration 時掉這個方法
ExportDefaultDeclaration(){

}
})

提取組件名稱、描述、props、methods、model

export default 生成的對應節點類型是 ExportDefaultDeclaration,declaration 屬性就是對應的組件的 options 了,遍歷 declaration 的屬性可以獲取到 namepropsmethodsmodel 等節點信息。

示例

let componentInfo = {}
traverse.default(jsAst, {
ExportDefaultDeclaration(path){
path.node.declaration.properties.forEach(item => {
switch (item.key.name) {
case 'props':
componentInfo.props = extractProps(item) // 提取 props
break;
case 'methods':
componentInfo.methods = extractMethods(item) // 提取 methods
break
case 'name':
componentInfo.name = item.value.value // 獲取組件名稱
break
case 'model':
componentInfo.model = extractModel(item) // 提取 model
break
default:
break;
}
});
}
})

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM