组件文档和预览效果
首先我列举一下目前比较主流的几个文档展示框架
- story-book
- vue-press
- dumi
这些文档展示框架都可以用于展示组件,但是他们都有一套自己的规则,也存在额外的学习成本。所以我选择不采用这些,而是通过上一节通过vite创建的项目本身来构建一个文档预览应用。
构建文档预览应用
我们当前启动项目只能看到如下的结果
对比主流的组件库应用,我们最起码需要达成下面几个条件:
- 一个关于组件的导航菜单
- 组件的预览效果
- 组件的实例代码
- 组件的简介(配置项,事件,额外说明等)
1.添加组件的导航菜单
这里我们引用vue-router,这里选择了v4版本。
并且引用了ant-design-vue作为ui库
yarn add vue-router@4 -D
yarn add ant-design-vue@next -D
在src目录下面增加一下文件夹
- router // 用于路由配置
- page // 用于编写预览页面
在page页面添加一个HelloPage
import { defineComponent } from 'vue';
import { Hello } from 'mis-design';
const HelloPage = defineComponent({
setup() {
return () => (<Hello title="123"></Hello>);
},
});
export default HelloPage;
配置路由
import { createRouter, createWebHistory } from 'vue-router';
import Hello from '../page/Hello'
const routes = [{
path: '/',
component: Hello
}]
const router = createRouter({
history:createWebHistory(),
routes
})
export default router;
修改main.ts
import { createApp } from 'vue'
import App from './App.vue'
import MyUI from '../packages/components'
import Routes from './router'
import 'ant-design-vue/dist/antd.css'
createApp(App).use(Routes).use(MyUI).mount('#app')
修改一下app.vue,更改页面布局,增加菜单栏等。
首先在page文件夹中新建一个Menus.tsx
import { defineComponent, watch, reactive } from 'vue';
import { Menu } from 'ant-design-vue';
import { RouterLink, useRoute } from 'vue-router';
interface IMenuItem {
name: string;
zh?: string;
path: string;
}
const menuMap: IMenuItem[] = [
{
name: 'Hello',
path: '/',
zh: '欢迎页',
},
];
const menus = defineComponent({
setup() {
const route = useRoute();
const state = reactive({
currentKey: [] as string[],
});
watch(route, (value) => {
const keys = value.path;
state.currentKey = [keys];
console.log(state.currentKey);
});
return () => (
<Menu mode="inline" selectedKeys={state.currentKey}>
{menuMap.map((item) => (
<Menu.Item key={item.path}>
<RouterLink to={item.path}>
{item.name}
{item.zh}
</RouterLink>
</Menu.Item>
))}
</Menu>
);
},
});
export default menus;
app.vue
<script setup lang="ts">
import { Layout } from 'ant-design-vue'
import Menus from './page/Menus'
import { RouterView } from 'vue-router'
const { Header, Sider, Content } = Layout;
import './style/index.css'
// import { Button } from './components/index'
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup
</script>
<template>
<Layout style="height:100%">
<Header style="text-align:left;">
<h1 style="color:#fff;display: flex;align-items: center;">
MY-UI
</h1>
</Header>
<Layout>
<Sider>
<Menus />
</Sider>
<Content>
<RouterView />
</Content>
</Layout>
</Layout>
</template>
2.组件预览+说明文档md
上面的HelloPage现在我们可以预览到Hello组件的展示效果,但是这才是最基础的,接下来我们要编写组件说明文档
// packages/components/Hello/readme.md
# Hello
# 配置项
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| ----- | ---- | ------ | ------ | ---- |
| title | --- | string | - | - |
接下来让md在页面展示,这里有一个很好用的库vite-plugin-md,更改vite.config.ts
import Markdown from 'vite-plugin-md'
export default defineConfig({
plugins: [
vue({ include: [/\.vue$/, /\.md$/] }),
vueJsx(),
Markdown()
],
}
我们在封装一个Preview.tsx用于显示我们的组件+源码+md
为了源码的高亮,我们需要prismjs
yarn add prismjs -D
// Preview.tsx
import { defineComponent, onMounted } from 'vue';
import { Collapse } from 'ant-design-vue';
import Prism from 'prismjs';
import 'prismjs/themes/prism-coy.css';
const Preview = defineComponent({
props: ['sourceCode', 'language', 'md'],
setup(props, { slots }) {
onMounted(() => {
Prism.highlightAll();
});
return () => (
<div>
<Collapse>
<Collapse.Panel
style={{
textAlign: 'left',
}}
header={
<div
style={{
background: '#fff',
padding: '16px',
}}
onClick={(e) => e.stopPropagation()}
>
{slots.default && slots.default()}
</div>
}
>
<pre class="language-html">
<code class={props.language || 'language-javascript'}>
{props.sourceCode}
</code>
</pre>
</Collapse.Panel>
</Collapse>
{props.md}
</div>
);
},
});
export default Preview;
最后,我们修改一下原来的Page/Hello.tsx
import { defineComponent } from 'vue';
import { Hello } from '../../packages/components';
import MD from '../../packages/components/Hello/readme.md';
import Preview from './Preview';
const HelloPage = defineComponent({
setup() {
return () => (
<div>
<Preview sourceCode={`<Hello title="123"></Hello>`} md={<MD />}>
<Hello title="123"></Hello>
</Preview>
</div>
);
},
});
export default HelloPage;
Hello.tsx引用Hello组件的路径有点难看,我们把他改成
import { Hello } from 'my-ui';
import MD from 'my-ui/Hello/readme.md';
这里需要给vite.config.ts配置resolve.alias,并且对应修改tsconfig.json增加paths
// vite.config.ts
resolve: {
alias: {
'my-ui': '/packages/components'
}
}
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"my-ui": ["packages/components"],
"my-ui/*": ["packages/components/*"]
},
}
}
最后优化一下markdown的展示效果,增加一个样式文件style/index.css
.markdown-body {
padding: 16px;
}
.markdown-body h1 {
text-align: left;
}
.markdown-body table {
width: 100%;
min-width: 720px;
margin: 2em 0;
font-size: 13px;
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier,
monospace;
line-height: 1.5;
border: 1px solid #e8e8e8;
}
.markdown-body table th,
.markdown-body table td {
padding: 12px;
border-color: #e8e8e8;
border-width: 1px 0;
}
.markdown-body table th {
padding-top: 14px;
border-width: 0 0 2px 0;
background-color: #e8e8e8;
}
.markdown-body table tbody tr {
-webkit-transition: all 0.3s;
transition: all 0.3s;
}
.markdown-body table tbody tr:hover {
background: rgba(60, 90, 100, 0.04);
}
.markdown-body table td:first-child {
width: 20%;
color: #595959;
font-weight: 600;
}
.markdown-body table td:nth-child(3) {
width: 22%;
color: #c41d7f;
font-size: 13px;
word-break: break-all;
}
.markdown-body table td:nth-child(4) {
width: 16%;
font-size: 13px;
}
.markdown-body hr {
margin: 12px 0;
}
最终效果达成!
可能相对来说不太好看,关于样式和预览页面可以自己优化调整
后续
关于组件库后面还有一些东西可以做,这里先记录一下,后续更新再发~
- 国际化
- 组件创建脚手架
- 实现组件的实时修改预览等