寫在前面:在我們的印象使用中,vue除了寫業務代碼沒有特別新奇的功能了,最近在着手探索了如何利用vue進行組件庫文檔編寫功能呢?
循序漸進進行學習~
本章介紹兩種文檔生成方法不同的地方以及優點和缺點
vuepress
網站參考連接:https://www.vuepress.cn/guide/
基於.md文檔生成可視化的ui界面
主要目錄結構為
. ├── docs │ ├── .vuepress (可選的) │ │ ├── components (可選的) │ │ ├── theme (可選的) │ │ │ └── Layout.vue │ │ ├── public (可選的) │ │ ├── styles (可選的) │ │ │ ├── index.styl │ │ │ └── palette.styl │ │ ├── templates (可選的, 謹慎配置) │ │ │ ├── dev.html │ │ │ └── ssr.html │ │ ├── config.js (可選的) │ │ └── enhanceApp.js (可選的) │ │ │ ├── README.md │ ├── guide │ │ └── README.md │ └── config.md │ └── package.json
目錄結構說明
目錄結構說明,根據圖片進行說明 :
- .vuepress 主要存放一些配置文件,入口文件
- docs存放.md文檔,主要用於生成文檔目錄的入口
- docs/.vuepress: 用於存放全局的配置、組件、靜態資源等。
- docs/.vuepress/components: 該目錄中的 Vue 組件將會被自動注冊為全局組件。
- docs/.vuepress/theme: 用於存放本地主題。
- docs/.vuepress/styles: 用於存放樣式相關的文件。
- docs/.vuepress/styles/index.styl: 將會被自動應用的全局樣式文件,會生成在最終的 CSS 文件結尾,具有比默認樣式更高的優先級。
- docs/.vuepress/styles/palette.styl: 用於重寫默認顏色常量,或者設置新的 stylus 顏色常量。
- docs/.vuepress/public: 靜態資源目錄。
- docs/.vuepress/templates: 存儲 HTML 模板文件。
- docs/.vuepress/templates/dev.html: 用於開發環境的 HTML 模板文件。
- docs/.vuepress/templates/ssr.html: 構建時基於 Vue SSR 的 HTML 模板文件。
- docs/.vuepress/config.js: 配置文件的入口文件,也可以是 YML 或 toml。
- docs/.vuepress/enhanceApp.js: 客戶端應用的增強。
這些的目錄結構以及說明在官網中都存在,主要配置文件雜居config.js的文件,頁面的左右連接等
config.js的基本配置就不多陳述:
https://www.vuepress.cn/config/#%E5%9F%BA%E6%9C%AC%E9%85%8D%E7%BD%AE
vue-styleguidist
一個基於vue-docgen-api編寫的可生成的組件庫文檔,在此基礎上衍生出了許多其他的組件庫功能,本文主要介紹兩個
- 基礎vue-styleguidist生成文檔
- 基於vue-styleguidist和vue-press生成文檔
用來對比兩種組件庫文檔的生成區別
先介紹vue-docgen-api 吧,想要查看vue-docgen-api的主要功能,我們需要借助node進行實現,
const { parse } = require('vue-docgen-api') //引入資源包 async function getData(){ var result = await parse('./vue/vue.vue')//異步加載需要解析的vue的文件 console.log(result) } getData()
獲得到vue-docgen-cli返回的字段內容和格式
{ displayName: 'Button', //vue組件中的名字 description: 'The only true button.',//組件的描述 tags: {}, //組件 exportName: 'default', docsBlocks: //vue組件底部的使用描述 [ 'Use vue live right here too\n\n````markdown\n```jsx live\n<Button>I’m transparent!</Button>\n```\n````\n\n```jsx live\n<Button>I’m transparent!</Button>\n```\n\nTo render an example as highlighted source code remove the live modifier\n\n```html\n<Button>I’m transparent!</Button>\n```' ], props://vue組件的prop的屬性值和描述信息 [ { name: 'color', description: 'The color for the button.', type: [Object], defaultValue: [Object] }, { name: 'size', description: 'The size of the button 其他的東西ddd', tags: {}, values: [Array], type: [Object], defaultValue: [Object] }, { name: 'onClick', description: 'Gets called when the user clicks on the button', tags: [Object], type: [Object], defaultValue: [Object] } ], events://vue組件內部暴露外部的事件 [ { name: 'click', description: '按鈕點擊成功emit事件', type: [Object], properties: [Array] } ], methods: undefined, slots: [ { name: 'test', scoped: true, description: '暴露出的插槽 ', bindings: [Array] } ] }
看內容可以看到,可以看到vue文件中的props和events以及slots等信息。了解了vue-docgen-api后,進行解析以及組件需要將頁面封裝即可
基於vue-docgen-cli和vue-press生成文檔
目錄結構配置:
項目中存在存放的兩個配置文件
- 用於生成.md文檔的docgen.config.js
- 用於解析.md文檔生成可視化頁面的vue-press配置文檔config.js
docgen.config.js 的配置文檔:
var path = require('path') module.exports = { componentsRoot: '../components1', //需要解析的組件目錄 相對路徑 components: '**/[a-z]*.{vue,ts,tsx}', //正則匹配組件的名字 outDir: './docs/components',//編譯后的組件的位置 // defaultExamples: true getDocFileName: (componentPath) => // componentPath.replace(/\.vue$/, '.md'), getDocFileName: (componentPath) => componentPath.replace(/\.vue$/, '.md'), templates: {//指定用於呈現組件的函數的對象。 //包裝所有其他組件的全局組件模板參見 component: require('templates/component'), events: require('templates/events'), methods: require('templates/methods'), props: require('templates/props'), slots: require('templates/slots'), // 如果組件是功能性的,則顯示為標記的靜態模板 functionalTag: '**functional**' }, require: [path.join(__dirname, 'global.requires.js')] //組件案例運行時候的demo }
vue-press的config.js文檔
文檔配置按照vuepress的配置文檔說明就可以了
const path = require('path') const glob = require('globby') const cwd = path.join(__dirname, '..') const { parse } = require('vue-docgen-api') const { renameComponentMd} =require('./fileinit.js') var vuepressConfig = async () => { renameComponentMd(cwd+'/components') const docFiles = glob.sync('components/**/*.md', { cwd }).map(f => '/' + f) //獲得.md文件的目錄結構 const components = await Promise.all( glob .sync('../../components1/**/[a-z].{vue,jsx,ts,tsx}', { cwd, absolute: true }) .map(async path => { return { name: (await parse(path)).displayName.replace(/[^a-zA-Z0-9_]/g, ''), path } }) )//建立文檔和組件的熱更新練習 console.log(docFiles) /** * {name:'button','**.vue} */ //引入fs文件目錄模塊 return { dest: path.join(__dirname, '../../dist'),//打包目錄 base: '/docgen/',//打包后內容 title: 'VuePress DocGen Live', themeConfig: {//頁面可視化配置 search: false, editLinks: true, nav:[ // 導航欄配置 {text: '前端基礎', link: '/accumulate/' }, {text: '前端基礎', items: [ { text: 'focus-outside', link: 'https://github.com/TaoXuSheng/focus-outside' }, { text: 'stylus-converter', link: 'https://github.com/TaoXuSheng/stylus-converter' }, ]}, ], sidebar: docFiles,//左側導航欄內容 markdown: { // 為每個代碼塊顯示行號 lineNumbers: true }, }, plugins: [ ['live'], [ '@vuepress/register-components', '@vuepress/nprogress', { //熱更新時進行檢測文件,當我們更改vue組件內容時候,能夠檢測到當前生成新的文檔 components, componentsDir: '../../components1' } ] ] } } module.exports = vuepressConfig;
配置packjson.json
"scripts": { "vuepress":"vuepress dev docs", //只啟動vuepress "comeMd":"vue-docgen --watch", //只生成.md文檔 "docs": "concurrently \"vue-docgen --watch\" \"vuepress dev docs\"", //同時生成.md文檔和生成可視化組件 "docs:build": "vue-docgen && vuepress build docs"//打包 },
可視化后的樣子
注意點:
vuepress 進行文檔渲染時候,保證生成的.md文件名字和目錄的名字是一值才可(也可以不一致,但是需要自己配置slider)
如:保持將文件夾下面的.md 和文檔目錄名字一致是最簡單的渲染文檔方式
'/components/common/popup.md', '/components/dialog/dialog.md', '/components/loading/loading.md', ]
因此需要規范化暴露.vue的命名
這個時候就需要我們規范化組件的命名了,統一管理組件的名字,或者在生成可視化組件時候,將.md文檔統一進行重新命名
規范生成.md文檔的命名
未規范前,rFlexFixed 的主暴露文件命名為index.vue 生成的文檔為index.md。而rFloat的主暴露的文件為rFloat.vue,生成后的.md文檔為rFloat.md 是符合我們規范的
可在配置中進行重命名,讓生成后的.md文檔和目錄的名字一致,重命名后的文檔
借助nodejs的fs模塊對文件重新命名
// 文件名字初始化 /** * 將組件文檔目錄中index.md替換成目錄名字+.md * 如 原文件 rAction/index.md=>rAction/rAction.md */ const fs = require('fs'); const path = require('path') var renameComponentMd =function(path){ var files = fs.readdirSync(path); files.forEach((file)=>{ //獲取當前文件目錄的地址 var currBaseDir = path+'/'+file; var fileStat = fs.statSync(currBaseDir); if(fileStat.isDirectory()){ var fileChildren = fs.readdirSync(currBaseDir);//獲取當前文件目錄的子目錄結 var indexMd = fileChildren.indexOf('index.md'); //當前文件目錄中存在index.md 則進行改名字 if(indexMd>-1){ var fsChildren = fileChildren[indexMd] var chPath = currBaseDir+'/'+fsChildren; if(fs.statSync(chPath).isFile()){ var renameFile = chPath.replace('index',file) fs.rename(chPath,renameFile,(err)=>{ if(err){ console.error(msg) }else{ } }) } } } }) }
重命名后的組件的一個缺點就是,當我們更改vue的文件內容注釋的時候,達不到熱更新效果---
着重介紹vue-styleguide 生成文檔