大家好我是来蹭饭,一个会点儿吉他和编曲,绞尽脑汁想傍个富婆的摸鱼大师。
今天跟大家分享使用Vuepress2.0 + Vue3.2 + Ant来搭建自己的组件库文档。
一. 前言
众所周知Vue已经来到了3.2的版本,使用<script setup>的语法糖给开发者带来了极大的便利。源于对Vue高版本的支持,本次使用Vuepress 2.0开发组件库文档,需求如下:
- 组件库能直接引用或二次封装
Ant的组件 - 组件库能显示组件代码供他人查阅
案例完成后,你将能看到这样婶儿的效果:
下面我将从安装,页面搭建,组件的引入与封装等章节跟大家分享组件库的搭建过程。废话少说,大家坐稳扶好,我们发车。
二. 安装
2.1 初始化
Vuepress 2.0对Node的版本支持为Node.js V12+,各单位注意自行升级Node的版本。
安装非常简单,cd到项目目录下然后一条命令即可
- 步骤1: 创建项目
yarn add -D vuepress@next
安装完毕后我们会发现项目变成这样了:
纳尼?
怎么只有一个node_modules?这跟我们用cli梭出来的项目差异这么大吗?我反复确认了安装命令已经完成,才敢继续下面的操作。
- 步骤2: 在
package.json中添加如下命令
{
"scripts": {
"docs:dev": "vuepress dev docs",
"docs:build": "vuepress build docs"
}
}
- 步骤3: 启动项目(完成页面搭建章节的config.js配置和README.md配置后启动)
yarn docs:dev
2.2 项目结构
Vuepress是用来写文档的,所以它的所有文件都会被包裹在docs文件夹下(可以理解成Vuepress项目的src文件夹)。你可以在自己的Vuepress项目中单独创建docs也可以让它“寄生”在已经存在的项目下(与原项目的运行互不影响):
本次案例我们以单独创建的Vuepress项目为例进行讲解。
经过我们的DIY后,docs文件夹初始化后的目录结构如下:
├─ docs
│ ├─ .vuepress
│ │ └─ config
│ │ └─ public
│ │ └─ config.js
│ └─ README.md
├─ .gitignore
└─ package.json
上述文件的作用分别是:
docs/.vuepress: 存放全局的配置、组件、静态资源等。docs/.vuepress/config: 存放页眉导航栏和子页面侧栏的配置文件。docs/.vuepress/public: 静态资源目录。docs/.vuepress/config.js: 配置文件的入口文件。docs/README.md: 文档的入口页面。
至此安装步骤算是完成了,接下来进入页面搭建的环节。完成后,我们就可以启动项目查看自己的文档了。
三. 页面搭建
写文档的过程就像写书,书本的每一页即为读者看到的内容。在Vuepress中
md文件就是书的页面,也是对应路由的结果。接下来我们通过配置config.js文件,md文件,页眉导航栏navbar以及页面侧栏sidebar来完成页面搭建。
在开始配置前我们先把目录结构调整如下:
├─ docs
│ ├─ .vuepress
│ │ └─ config
│ │ │ └─ navbar.js
│ │ │ └─ sidebar.js
│ │ └─ public
│ │ │ └─ img
│ │ └─ config.js
│ └─ README.md
├─ .gitignore
└─ package.json
3.1 config.js配置
themeConfig中logo寻址的路径默认是public文件夹,将对应的logo图片放入img文件夹中。
module.exports = {
// 站点配置
lang: 'zh-CN',
title: 'UI-LIB',
description: '组件库',
head: [ // 注入到当前页面的 HTML <head> 中的标签
['link', {
rel: 'icon',
href: '/img/logo.png'
}], // 增加一个自定义的 favicon(网页标签的图标)
],
// 主题和它的配置
theme: '@vuepress/theme-default',
themeConfig: {
logo: '/img/logo.png',
}
}
3.2 入口README.md配置
---
home: true
heroImage: /img/logo.png
actionText: 快速上手 →
actionLink: /zh/`guide/
features:
- title: 简洁至上
details: 以 Markdown 为中心的项目结构,以最少的配置帮助你专注于写作。
- title: Vue驱动
details: 享受 Vue + webpack 的开发体验,在 Markdown 中使用 Vue 组件,同时可以使用 Vue 来开发自定义主题。
- title: 高性能
details: VuePress 为每个页面预渲染生成静态的 HTML,同时在页面被加载的时候,将作为 SPA 运行。
footer: MIT Licensed | Copyright © 2018-present Evan You
---
当完成上述配置后,通过yarn docs:dev运行项目,此时项目会新增.cache和.temp文件,不用管它们,直接看运行效果:
一个最基础的文档页面就诞生了!接下来我们进入导航栏和侧栏的配置。
3.3 navbar.js 导航栏配置
导航栏的配置,是配置二级页面路由的过程(外链导航除外),我们希望导航栏实现这样的效果:
- 导航栏包含组件,文档,工具箱三个选项
- 点击组件,能路由到组件页面
- 鼠标经过文档时,弹出二级菜单选项,点击直接进入二级菜单页
- 工具箱的展开内容是一些线上地址的链接,点击后跳转线上页面
接下来我们逐步实现上述需求:
- 步骤1: 调整项目结构,在
docs中添加components和document两个文件夹,具体内容如下:
- 步骤2: 将navbar.js文件引入config.js中
const navbar = require('./config/navbar')
module.exports = {
// 站点配置
lang: 'zh-CN',
title: 'UI-LIB',
description: '组件库',
head: [ // 注入到当前页面的 HTML <head> 中的标签
['link', {
rel: 'icon',
href: '/img/logo.png'
}], // 增加一个自定义的 favicon(网页标签的图标)
],
// 主题和它的配置
theme: '@vuepress/theme-default',
themeConfig: {
logo: '/img/logo.png',
navbar,
sidebarDepth: 2, // 侧边栏显示2级
}
}
- 步骤3: 在
docs/.vuepress/config/navbar.js中做出如下配置:
module.exports = [{ text: '组件', link: '/components/' }, { text: '文档', children: [{ text: '介绍', link: '/document/introduction/' }, { text: '注意事项', link: '/document/tips/' }, ]
},
{
text: '工具箱',
children: [{
text: '在线编辑',
children: [{
text: '图片压缩',
link: 'https://tinypng.com/'
}]
},
{
text: '在线服务',
children: [{
text: '阿里云',
link: 'https://www.aliyun.com/'
},
{
text: '腾讯云',
link: 'https://cloud.tencent.com/'
}
]
},
{
text: '博客指南',
children: [{
text: '掘金',
link: 'https://juejin.im/'
},
{
text: 'CSDN',
link: 'https://blog.csdn.net/'
}
]
}
]
}
]
这里讲解一下各字段的含义
-
text: 显示在导航栏上的文字信息
-
link: 路由地址显示的页面(类似于router中的component)会自动寻址到指定目录下的
README.md,把它作为主入口显示出来。link字段也可以配置线上地址,点击后跳转到线上页面。默认页面路由地址如下:文件的相对路径 页面路由地址 /README.md//components/README.md/components/ -
children: 子路由的嵌套信息,可多层嵌套,上述示例已给出
以工具箱配置为例,效果如图所示,结合代码更好理解:
至此我们的导航栏配置工作完成。
由此可见,导航栏上每一个能进入二级页面的导航,都要对应一个页面文件:
| 导航栏选项 | 对应文件 |
|---|---|
组件 | components |
文档/介绍 | document/introduction |
文档/注意事项 | document/tips |
现在进入组件页面,里面还是一片空白。接下来我们通过配置sidebar.js,实现二级页面的侧栏切换功能。
3.4 sidebar.js 侧栏配置
侧栏的承载的信息比较多,因此我们在
docs/.vuepress/config/sidebar.js中配置整合后的侧栏信息。每个页面的侧栏交由该页面独立控制,以components页面为例进行侧栏配置。
- 步骤1: config.js引入侧栏并使用
const navbar = require('./config/navbar')
const sidebar = require('./config/sidebar')
module.exports = {
// 站点配置
lang: 'zh-CN',
title: 'UI-LIB',
description: '组件库',
head: [ // 注入到当前页面的 HTML <head> 中的标签
['link', {
rel: 'icon',
href: '/img/logo.png'
}], // 增加一个自定义的 favicon(网页标签的图标)
],
// 主题和它的配置
theme: '@vuepress/theme-default',
themeConfig: {
logo: '/img/logo.png',
navbar,
sidebar,
sidebarDepth: 2, // 侧边栏显示2级
}
}
- 步骤2: 在
config/sidebar.js中导出配置
module.exports = {
'/components/': require('../../components/sidebar'),
}
-
步骤3: 配置components文件,结构修改如下:
pages:当前页面下的子路由,目前新增了Button,InputNumber和Slider3个子页面
sidebar.js:当前页面的侧栏配置
-
步骤4: 配置components文件中的sidebar.js:
module.exports = [{
text: '通用',
collapsable: true,
children: [{
text: 'Button 按钮',
link: '/components/pages/Button',
}]
}, {
text: '数据录入',
collapsable: true,
children: [{
text: 'Slider 滑动组件',
link: '/components/pages/Slider',
}]
},
{
text: '数字输入框',
collapsable: true,
children: [{
text: 'InputNumber 数字输入框',
link: '/components/pages/InputNumber',
}]
},
]
sidebar中的字段与navbar类似,这里不多做赘述,配置完成后就能正常点击components下的侧栏了。
至此页面搭建工作完成!接下来将Ant引入文档中,进一步完善我们的组件库。
四. 组件的引入与封装
本章节需要解决以下两个问题:
Ant引入Vuepress后如何注册并使用?- 二次封装组件时,我们希望在
.vue文件中操作,之后使用md文件引入.vue文件。如何让md文件正确识别.vue文件?
下面我将逐步讲解这两个问题的解决方式。
4.1 引入Ant
- 步骤1: 修改
.vuepress文件夹结构,新增clientAppEnhance.js文件(迁移特性Vuepress1中名称为enhanceApp.js),该文件的作用是增强客户端应用
├─.vuepress
│ └─ config
│ │ └─ navbar.js
│ │ └─ sidebar.js
│ └─ public
│ │ └─ img
│ └─ clientAppEnhance.js
│ └─ config.js
- 步骤2: 安装
Ant
yarn add ant-design-vue@next
- 步骤3: 配置
clientAppEnhance.js文件
import Antd from 'ant-design-vue'
import 'ant-design-vue/dist/antd.css'
import { defineClientAppEnhance } from '@vuepress/client'
export default defineClientAppEnhance(({ app, router, siteData }) => {
app.use(Antd)
})
到这里使用Ant的前置工作已经完成。
4.2 识别.vue文件
- 步骤1: 安装
@vuepress/plugin-register-components插件,在Vuepress1.0中,md文件能自动识别导出的.vue文件,Vuepress2.0中需要安装插件并做好配置
yarn add @vuepress/plugin-register-components@next
- 步骤2:
config.js中配置修改如下:
const {
path
} = require('@vuepress/utils')
const navbar = require('./config/navbar')
const sidebar = require('./config/sidebar')
module.exports = {
// 站点配置
lang: 'zh-CN',
title: 'UI-LIB',
description: '组件库',
head: [ // 注入到当前页面的 HTML <head> 中的标签
['link', {
rel: 'icon',
href: '/img/logo.png'
}], // 增加一个自定义的 favicon(网页标签的图标)
],
// 主题和它的配置
theme: '@vuepress/theme-default',
themeConfig: {
logo: '/img/logo.png',
navbar,
sidebar,
sidebarDepth: 2, // 侧边栏显示2级
},
plugins: [
[
'@vuepress/plugin-register-components',
{
componentsDir: path.resolve(__dirname, './components')
}
],
]
}
- 步骤3: 在
.vuepress文件夹中新建components文件夹,里面存放vue组件,文件结构如下:
├─.vuepress
│ └─ components
│ │ └─ Button.vue
│ └─ config
│ │ └─ navbar.js
│ │ └─ sidebar.js
│ └─ public
│ │ └─ img
│ └─ clientAppEnhance.js
│ └─ config.js
至此md文件就能无需引入即可自动识别.vuepress/components/下所有的vue组件了。继续完成下面的步骤,预览效果。
- 步骤4:
Button.vue文件添加Ant中Button的代码:
<template>
<a-button type="primary">Primary Button</a-button>
<a-button>Default Button</a-button>
<a-button type="dashed">Dashed Button</a-button>
<a-button type="text">Text Button</a-button>
<a-button type="link">Link Button</a-button>
</template>
- 步骤5:
docs/components/pages/Button.md文件直接引入Button.vue:
常用的操作按钮。
## 基础用法
基础的按钮用法。
<Button />
至此组件库初具雏形,我们看看效果:
现在还剩一些问题待解决:
- 如果组件业务逻辑不复杂,比如
Button.vue中只有template代码,并不包含业务逻辑功能。这种情况下能否直接将.vue文件的内容写在md文件里? - 如何在组件底部添加"显示代码"的按钮,供他人查阅组件代码?
我们通过本文最后的part来解决这些问题。
4.3 直接书写vue语法
上述问题可以通过安装vuepress-plugin-demoblock-plus插件,再配置config.js解决。
- 步骤1: 安装插件。
yarn add vuepress-plugin-demoblock-plus -D
- 步骤2: 修改config.js中
plugins的配置:
plugins: [
[
'@vuepress/plugin-register-components',
{
componentsDir: path.resolve(__dirname, './components')
}
],
[ 'vuepress-plugin-demoblock-plus' ]
]
- 步骤3: 修改
docs/components/pages/Button.md文件:
# Button 按钮
常用的操作按钮。
## 基础用法
基础的按钮用法。
:::demo 使用`type`、`plain`、`round`和`circle`属性来定义 Button 的样式。
```vue
<template>
<a-button type="primary">Primary Button</a-button>
<a-button>Default Button</a-button>
<a-button type="dashed">Dashed Button</a-button>
<a-button type="text">Text Button</a-button>
<a-button type="link">Link Button</a-button>
</template>
```(避免转义,使用时去掉整个括号的内容)
:::
我们看看预览效果:
到这一步组件库的基本功能就实现了。接下来我们简单封装一个自己的InputNumber组件。
4.4 展示二次封装的业务组件
- 步骤1: 更改
.vuepress文件夹结构:
├─.vuepress
│ └─ components
│ │ └─ InputNumber.vue
│ └─ config
│ │ └─ navbar.js
│ │ └─ sidebar.js
│ └─ public
│ │ └─ img
│ └─ clientAppEnhance.js
│ └─ config.js
- 步骤2:
InputNumber.vue文件添加如下代码:
<template>
<a-input v-model:value="value" placeholder="Basic usage" />
</template>
<script setup>
import { ref, defineProps } from "vue";
const props = defineProps({
defaultValue:String
})
const value = ref(props.defaultValue);
</script>
- 步骤3: 修改
docs/components/pages/InputNumber.md文件:
# Input 输入
常用的操作按钮。
## 基础用法
基础的输入框用法。
:::demo
```vue
<template>
<InputNumber :defaultValue="defaultValue"/>
</template>
<script setup>
import { ref } from 'vue';
const defaultValue = ref('来蹭饭')
</script>
```(避免转义,使用时去掉整个括号的内容)
:::
这样一个简单封装的组件就完成了,InputNumber.vue接收到了从InputNumber.md传入的参数,来看看最终的预览效果:
大功告成!通过上述方法我们就可以为所欲为地搭建自己的组件库了。
五. 尾巴
读到这里你也不易,写到这里我也不易。不嫌麻烦的话欢迎点赞,评论,收藏,你们的支持是我创作的最大动力。
我是来蹭饭,一个会点儿吉他和编曲,绞尽脑汁想傍个富婆的摸鱼大师,希望本次的分享对你有帮助。
打完收工,纪念一下掘金的第一篇文章。