全网最详细的从0到1的turbo pnpm monorepo的前端工程化项目[vitePress篇]
- 前言
- 选型
- 为什么选择VitePress
- 安装VitePress
- 运行
- 优化默认UI
- 使用自定义UI
- 编辑自定义布局
- 编写home页面组件
- 编写page页面组件
- 结语
前言
一个好的工程化项目,必然有一个好的文档管理,这样才算称得上一个好的工程化,也大大提高后面的工作和文档查找的效率!组件库文档可以帮我们解决
- 不知道项目中有哪些公共组件(比如组员写的组件,但是你并不知道),导致重复开发。
- 复用组件时需要再去翻代码,看看怎么使用,传什么参数。
- 以前写的代码,需要修改或者重构时,无从下手
选型
组件文档库是现代前端开发的重要组成部分,它可以提高团队协作效率、减少重复工作,并为项目提供一个可靠的知识库。以下是几个最受欢迎的组件文档库工具:
-
VitePress: 是一个基于 Vite 构建工具的静态网站生成器,专为编写文档而设计。它是 Vue.js 生态系统中的一部分,旨在提供简单、快速且易于使用的文档编写和展示解决方案。
-
Storybook:Storybook 是目前最流行的组件文档库工具之一。它支持 React、Vue、Angular 等主流前端框架,可以帮助开发人员将组件独立测试和展示,并提供了一个干净、易于导航的文档网站。Storybook 还提供了许多插件和工具,可帮助你更轻松地管理组件库。
-
Styleguidist:Styleguidist 是另一个流行的组件文档库工具,它专注于样式组件库的构建和文档化。它支持 React 和 Vue,并提供了一个动态的文档网站,可用于展示样式组件和交互效果。Styleguidist 还提供了许多可定制的主题和插件,可帮助你创建专业级的样式文档。
-
Docz:Docz 是一个基于 Markdown 的组件文档库工具,旨在帮助开发人员快速构建漂亮的文档网站。它支持 React 和 Vue 组件,并提供了一个干净、可定制的文档网站模板。Docz 还提供了许多插件和工具,可帮助你更轻松地管理和展示组件库。
-
Catalog:Catalog 是一个简单而强大的组件文档库工具,它支持 React 和 Vue 等主流前端框架,并提供了一个可定制的文档网站。Catalog 还提供了一些有用的功能,如交互式代码演示、快速搜索和样式调试工具。
-
Dumi: 是一个基于 Umi 的 React 文档工具,专门用于开发 React 组件的文档网站。是一个适用于 React 组件文档开发的工具,它可以帮助开发人员快速创建漂亮、易于维护的文档网站。Dumi 具有方便的 Markdown 编写、实时预览、丰富的组件库等特点和功能,可以大大提高开发效率和文档质量。
-
Docsify: 是一个轻量级的文档网站生成工具,它可以帮助你快速创建漂亮、易于阅读和导航的文档网站。是一个简单轻便的文档网站生成工具,适用于快速创建漂亮、易于阅读和导航的文档网站。它支持 Markdown 编写、自动生成导航和侧边栏、可定制主题样式等特点,使得文档编写和展示变得简单而高效。
为什么选择VitePress
VitePress 是一个轻量级、快速且易于使用的文档生成工具,适用于编写和展示各种类型的文档。它是 Vue.js 生态系统中的一部分,与 Vue 组件开发非常契合,可以帮助开发人员快速构建漂亮的文档网站。 而且VitePress 的一些特点和功能:
-
快速:VitePress 构建工具使用了现代化的开发服务器和打包器 Vite,可以实现秒级的冷重载和快速的热更新,以提供流畅的开发体验。
-
Markdown 支持:VitePress 使用 Markdown 格式编写文档,Markdown 是一种易于学习和编写的标记语言,可以方便地将文档内容转换为美观的 HTML。
-
主题定制:VitePress 提供了易于定制的默认主题,并支持使用 Vue 组件进行自定义主题开发。你可以根据自己的需求,轻松地创建适合项目风格的文档主题。
-
侧边栏和导航:VitePress 提供了一个自动生成的侧边栏和导航工具,可根据 Markdown 文件结构自动创建菜单和链接,使读者可以方便地浏览和导航文档内容。
-
部署简单:VitePress 生成的静态网站可以轻松部署到各种静态网站托管服务(如 Netlify、GitHub Pages 等)或自行托管,没有复杂的构建过程。
安装VitePress
接上篇文章,在apps下新建 docs 文件夹, 在docs下初始化并生成package.json,安装vitepress 和 vue, 官网安装向导
$ cd apps && mkdir docs && cd docs
$ pnpm init
$ pnpm add -D vitepress vue // 或者在根目录下 pnpm add -D vitepress vue --filter="docs"
$ pnpm vitepress init // apps/docs下
pnpm vitepress init 运行时,按照提示一步一步跟自己的需要来进行配置,最终生成这样的的
docs
├─ .vitepress
│ ├─ cache
│ └─ config.ts
├─ api-examples.md
├─ index.md
├─ markdown-examples.md
└─ package.json
这个全在官网上的,没啥好说的, 唯一的我这边吧命令稍微改下,吧 docs:dev,docs:build,docs:preview 全部改成dev,build,preview 这样在turbo 任务的时候好处理,并且在根目录下加入指令 “dev”: “turbo run dev”,
运行
直接在跟目录下 或者在apps/docs下运行都可以
$ pnpm run dev // 或者在根目录下 pnpm run dev --filter="docs"
运行的效果
优化默认UI
- 基础配置
修改 apps/docs/.vitepress/config.ts文件,加入全局搜索
export default defineConfig({
title: "Robin Design",
description: "为业余而生",
themeConfig: {
search: {
provider: 'local'
},
// https://vitepress.dev/reference/default-theme-config
nav: [
{ text: '首页', link: '/' },
{ text: '组件', link: '/markdown-examples' }
],
sidebar: [
{
text: 'Examples',
items: [
{ text: 'Markdown Examples', link: '/markdown-examples' },
{ text: 'Runtime API Examples', link: '/api-examples' }
]
}
],
socialLinks: [
{ icon: 'github', link: 'https://github.com/vuejs/vitepress' }
]
}
})
- 新建css, 在.vitepress/theme下新建 common.css和index.ts
common.css
:root {
--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #bd34fe 30%, #41d1ff);
--vp-home-hero-image-background-image: linear-gradient(-45deg, #bd34fe 50%, #47caff 50%);
--vp-home-hero-image-filter: blur(44px);
}
.VPNavBarTitle>.title>span{ height: var(--vp-nav-height);
font-size: 24px;
font-weight: 700;
color: var(--vp-c-text-1);
line-height: calc(var(--vp-nav-height) - 4px);
background: #005de0 -webkit-linear-gradient(left,#005de0,#febaf7 50%,#bd34fe 90%,#561214) no-repeat 0 0;
background-size: 20% 100%;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-decoration: underline;
-webkit-animation: slideShine 2s linear infinite;
animation: slideShine 2s linear infinite;
}
.clip{
background: var(--vp-home-hero-name-background);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: var(--vp-home-hero-name-color);
}
@-webkit-keyframes slideShine {
0% {
background-position: 0 0
}
to {
background-position: 100% 100%
}
}
@keyframes slideShine {
0% {
background-position: 0 0
}
to {
background-position: 100% 100%
}
}
index.ts
import DefaultTheme from 'vitepress/theme'
import './common.css'
export default DefaultTheme
- 优化首页,这个首页没有做很多处理,首页弄成跟官网一样,这个后期有更好的在做处理,这个文件在apps/docs/index.md
---
layout: home
hero:
name: "Robin Design"
text: "为了业余而生 "
tagline: Robin更表现出我当下的心境
actions:
- theme: brand
text: 快速开始
link: /markdown-examples
- theme: alt
text: GitHub
link: /api-examples
features:
- title: 蓝色知更鸟
details: 蓝色知更鸟的身体主要是蓝色的,头部有白色斑点,翅膀上有黑色条纹
- title: 红胸知更鸟
details: 红胸知更鸟的胸部是橙红色的,头部和背部是深灰色的,腹部是白色的
- title: 紫翅知更鸟
details: 紫翅知更鸟的羽毛呈现出紫色的光泽,具有黑色的头部和背部
- title: 黄腹知更鸟
details: 黄腹知更鸟的身体是鲜黄色的,头部有一些淡绿色的斑块
- title: 绿头鸭
details: 绿头鸭的雄性具有独特的羽毛颜色,头部呈现出绿色,身体大部分是灰褐色的
效果图
使用自定义UI
我这边不太喜欢默认的,修改的需要自己查好多文档来进行处理,很耗时。这里我使用自定义的方式来实现,
编辑自定义布局
修改theme/index.ts 文件
import './common.css'
import Layout from './Layout.vue'
export default {
Layout: Layout
}
新增 theme/Layout.vue
<script setup>
import { useData } from 'vitepress'
import NotFound from './NotFound.vue'
import Home from './Home.vue'
import Page from './page/index.vue'
const { page, frontmatter } = useData()
</script>
<template>
<Home v-if="frontmatter.layout === 'home'" />
<NotFound v-else-if="page.isNotFound" />
<Page v-else />
</template>
新增 theme/NotFound.vue 404页面, Home和Page组件请看下面
编写home页面组件
新增 theme/Home.vue
<template>
<div class="warp">
<div class="warp-banner">
<div class="card-box">
<div class="card-box-left">
<div class="title">{{ frontmatter.hero.name }}</div>
<div class="desc">{{ frontmatter.hero.text }}</div>
<div class="tagline">{{ frontmatter.hero.tagline }}</div>
<div class="button-warp">
<a>快速开始</a>
<a>GitHub</a>
</div>
</div>
<div class="card-box-right">
<img src="/public/dev.png" />
</div>
</div>
<div class="big-title">知更鸟</div>
<div class="card-box">
<div class="card-box-left title-bg">
<div class="title"></div>
</div>
<ul class="card-box-right feat-warp">
<li class="feat-item" v-for="(item,inx) in frontmatter.features" :key="inx">
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="200" height="200">
<path d="M83.5 517.7a428.7 432.5 0 1 0 857.4 0 428.7 432.5 0 1 0-857.4 0Z" :fill="item.color"></path>
<path d="M517.2 711.1c-22-6.7-44.5-11.5-65.2-22.1-76.3-38.9-115.2-116.6-97.9-203.5 8.5-42.7-28.5-84.6-71.6-75.4-23.5 5-47.8 6.1-71.7 9.3-5 0.7-9.7 2.5-13-4.2 20.2-4.9 40.3-9.5 60.4-14.6 19.2-4.8 32.6-15.9 41.3-34.4 23.9-50.4 80.1-57.7 116.4-15.1 21.8 25.5 36.7 55.8 55.4 83.5 4 5.9 8.3 11.5 12.4 17.2 6.2 14.5 16.5 17.4 30.6 11.5 26.1-10.9 52.4-21.4 78.7-32 71.3-28.2 142.7-56.4 214.1-84.6 0.4 1.5 1.2 2.7 0.9 3.3-35.6 60.3-76.1 116.9-128.7 163.9-29.8 26.7-61.9 49.7-104.6 49.4-8.4 0-7.9 5.6-8.5 11.1-4.2 39.7 8.4 73.9 36.2 101.9 36.1 36.4 57.7 79.7 65.6 130 1.1 6.8 3.1 14 0 20.9-0.1 0.2-0.8 0.4-1.2 0.3-0.5-0.2-0.9-0.6-1.4-0.9-4.9-19.2-18-33.5-30.5-47.6-31.6-35.3-69.9-60.1-117.7-67.9z" fill="#FFFFFF"></path>
<path d="M593 431.4c-26.2 10.6-52.6 21.1-78.7 32-14.1 5.9-24.4 3-30.6-11.5 65.9-51.3 131.8-102.5 197.6-153.8 1.1 1 2.2 2.1 3.3 3.1-14.5 20-29.1 39.9-43.3 60.1-16.2 23.3-34.2 45.3-48.3 70.1zM517.2 711.1c47.8 7.8 86.1 32.6 117.7 68.1 12.5 14 25.6 28.3 30.5 47.6-19.5-13-39-25.9-62.8-29.6-4.2-0.6-7.1-2.8-8.7-6.5-15.3-36.5-43.4-60.6-76.7-79.6z" fill="#C5FFDF"></path>
</svg>
<div class="item-info">
<div class="title">{{item.title}}</div>
<div class="desc">{{item.details}}</div>
</div>
</li>
</ul>
</div>
</div>
<h1>我是首页</h1>
<Content />
</div>
</template>
<script setup>
import { useData } from 'vitepress'
const { frontmatter } = useData()
</script>
<style scoped>
.....
.item-info .desc{
line-height: 24px;
font-size: 13px;
color: #3c3c43;
opacity: 0.6;
}
</style>
效果图如下
编写page页面组件
新增 theme/page文件夹,在page文件夹新增footer.vue,header.vue, sidebar.vue, index.vue
编写footer.vue
<template>
<div class="page-footer">
<span>{{ theme.footer.copyright }}</span>
</div>
</template>
<script setup>
import { useData } from 'vitepress'
const { theme } = useData()
</script>
<style scoped>
.page-footer {
position: relative;
background-color: #f3f3f3;
height: 26px;
font-size: 12px;
text-align: center;
color: #666;
flex: 0 0 auto
}
.page-footer>span {
opacity: .4;
line-height: 26px
}
</style>
编写header.vue
<template>
<div class="page-header">
<div class="left">
<span class="slide-title">{{ site.title }}</span>
</div>
<div class="right">
<ul class="ul-nav">
<li v-for="nav in theme.nav" :key="nav.link">
<a :href="nav.link">{{ nav.text }}</a>
</li>
</ul>
<div class="user">
<svg viewBox="0 0 1024 1024" width="30" height="30" class="icon"><path data-v-074131e3="" d="M530.324211 630.74807l27.486315 46.708772 37.367018 63.41614a3.413333 3.413333 0 0 1 0 5.030176q-31.079298 30.181053-61.799298 60.901053c-1.796491 1.796491-2.694737 1.97614-4.670878 0l-62.158596-61.080702c-1.437193-1.437193-1.97614-2.515088 0-4.491228q31.977544-53.894737 63.775439-107.789474l1.437193-2.155789z" p-id="7910"></path><path data-v-074131e3="" d="M842.374737 826.385965a9.162105 9.162105 0 0 1-8.982456-8.802807c-2.874386-87.848421-57.487719-196.53614-156.115088-234.442105a9.341754 9.341754 0 0 1-5.569123-6.28772 8.802807 8.802807 0 0 1 2.15579-8.08421c42.037895-45.630877 60.721404-89.824561 60.541754-140.665263a181.804912 181.804912 0 0 0-72.757895-143.719299 9.162105 9.162105 0 0 1-2.694737-12.575438 8.982456 8.982456 0 0 1 12.39579-2.515088 197.614035 197.614035 0 0 1 81.021754 159.528421 211.806316 211.806316 0 0 1-56.769122 143.719298c98.447719 44.373333 152.701754 155.396491 155.755789 245.580351a8.982456 8.982456 0 0 1-8.623158 9.341755z m-566.613333 0a8.802807 8.802807 0 0 1-8.443509-9.521404 258.515088 258.515088 0 0 1 206.596491-239.112982A158.091228 158.091228 0 0 1 415.169123 538.947368a8.982456 8.982456 0 0 1 13.114386-12.395789 141.38386 141.38386 0 0 0 211.267368-8.26386 8.982456 8.982456 0 1 1 13.832983 11.317895 157.73193 157.73193 0 0 1-70.242807 49.403509 259.054035 259.054035 0 0 1 200.488421 237.136842 8.982456 8.982456 0 0 1-8.623158 9.521403 8.802807 8.802807 0 0 1-9.341755-8.443508 240.909474 240.909474 0 0 0-480.920701 0 8.982456 8.982456 0 0 1-8.982456 9.162105z m360.735438-495.292632a9.162105 9.162105 0 0 1-6.467368-2.694737 141.204211 141.204211 0 0 0-197.614035-1.257543 9.162105 9.162105 0 0 1-12.755088 0 8.982456 8.982456 0 0 1 0-12.755088 159.169123 159.169123 0 0 1 223.663158 1.616842 8.982456 8.982456 0 0 1-6.28772 15.270175z" p-id="7911"></path><path data-v-074131e3="" d="M591.584561 512a84.794386 84.794386 0 0 1-61.978947-26.947368 85.153684 85.153684 0 1 1 0-116.77193 85.153684 85.153684 0 1 1 61.978947 143.719298z m0-123.778246a38.804211 38.804211 0 1 0 38.624562 38.624562 38.624561 38.624561 0 0 0-38.624562-38.624562z m-123.778245 0a38.804211 38.804211 0 1 0 38.624561 38.624562A38.804211 38.804211 0 0 0 467.087719 388.221754z"></path></svg>
<span>Robin</span>
</div>
</div>
</div>
</template>
<script setup>
import { useData } from 'vitepress'
const { site, theme } = useData()
</script>
<style scoped>
.page-header {
position: relative;
height: 44px;
padding-right: 20px;
background-color: #222833;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
flex: 0 0 auto;
}
.page-header .left{
position: relative;
font-size: 20px;
padding: 0 10px;
border-right: 2px solid rgba(255,255,255,0.1);
}
.page-header .right{
position: relative;
display: flex;
align-items: center;
flex: 1;
text-align: left;
height: 100%;
padding-left: 10px;
}
.slide-title{
font-size: 20px;
background: #005de0 -webkit-linear-gradient(left,#005de0,#febaf7 50%,#ff0 90%,#bd34fe) no-repeat 0 0;
background-size: 20% 100%;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-decoration: underline;
-webkit-animation: slideShine 3s linear infinite;
animation: slideShine 3s linear infinite;
}
.ul-nav{
flex: 1;
border-right: 2px solid rgba(255,255,255,0.1);
margin: 0 10px;
font-size: 14px;
}
.ul-nav>li {
position: relative;
display: inline-block;
height: 100%;
padding: 12px 15px;
cursor: pointer;
z-index: 2
}
.ul-nav>li a {
color: #fff;
opacity: .7
}
.ul-nav>li.active:before {
content: "";
position: absolute;
top: 0;
left: 0;
opacity: .1;
background: #fff;
display: inline-block;
height: 100%;
width: 100%
}
.ul-nav>li.active:after {
content: "";
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
border-bottom: 4px solid #378cff;
border-right: 18px solid transparent;
border-left: 18px solid transparent
}
.ul-nav>li.active a {
opacity: 1;
}
.user{
position: relative;
z-index: 2;
background: hsla(0,0%,100%,.2);
display: inline-block;
height: 35px;
border-radius: 20px;
padding: 0 15px;
cursor: pointer;
margin-left: 15px;
}
.user>svg{
vertical-align: middle;
fill: #fff;
}
.user>span{
vertical-align: sub;
}
</style>
编写sidebar.vue
<template>
<nav class="nav-warp">
<h2 class="nav-title active">
<svg class="svg-icon nav" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" >
<path d="M444.188444 84.423111V917.048889H967.111111z" fill="#00F4FC"></path>
<path d="M444.302222 510.407111v406.755556H967.111111L711.793778 510.407111H444.302222z" fill="#02BEFF"></path>
<path d="M444.188444 510.407111H56.888889v406.755556h387.299555z" fill="#005FE0"></path>
</svg>
<span>入门</span>
</h2>
<ul class="nav-items">
<li class="nav-item">
<a class="nav-group">
<span>规范</span>
<span class="icon-chevron-down">
<svg width="1em" height="1em" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M12.1464466,6.85355339 L8.35355339,10.6464466 C8.15829124,10.8417088 7.84170876,10.8417088 7.64644661,10.6464466 L3.85355339,6.85355339 C3.65829124,6.65829124 3.65829124,6.34170876 3.85355339,6.14644661 C3.94732158,6.05267842 4.07449854,6 4.20710678,6 L11.7928932,6 C12.0690356,6 12.2928932,6.22385763 12.2928932,6.5 C12.2928932,6.63260824 12.2402148,6.7597852 12.1464466,6.85355339 Z" fill-rule="nonzero" class="ng-tns-c41-5"></path>
</g>
</svg>
</span>
</a>
</li>
</ul>
</nav>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useData } from 'vitepress'
const { theme } = useData()
const navInx = ref(0)
const groupInx = ref(0)
</script>
<style scoped>
.svg-icon {
width: 1.2em;
height: 1.2em;
vertical-align: -0.2em;
overflow: hidden;
}
.sidebar{
position: relative;
display: inline-block;
border-right: 1px solid #ebeff2;
color: #3F536E;
width: 190px;
height: 100%;
background: #fff;
transition: all .3s;
}
.happy-scroll{
width: 190px;
height: 100%;
}
.nav-child-item{
position: relative;
}
.btn-svg{
display: inline-block;
position: fixed;
left: 162px;
z-index: 2;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
transition: all .3s;
}
.btn-svg svg{
transform: rotate(-90deg);
}
.nav-warp{
font-size: 14px;
width: 190px;
padding-bottom: 15px;
}
.nav-title{
position: relative;
padding: 0 0 5px 20px;
color: #657085;
font-size: 16px;
letter-spacing: 0;
text-transform: uppercase;
font-weight: 600;
margin-top: 15px;
}
.nav-title .nav{
position: absolute;
top: 1px;
left: 2px;
display: none;
font-size: 13px;
}
.nav-title.active .nav{
display: inline-block;
}
.nav-group{
display: block;
position: relative;
padding: 6px 0 6px 20px;
color: #575d6c;
font-weight: 600;
z-index: 2;
}
.nav-group:hover{
color: #1a6fe3;
}
.nav-group i{
position: absolute;
top: 50%;
right: 16px;
margin-top: -7px;
color: #A8C6DF;
font-size: 14px;
transition: all .3s;
}
.nav-items{
font-size: 14px;
font-weight: normal;
line-height: 1.8;
}
.nav-item{
position: relative;
}
.nav-child-items{
display: none;
}
.active .nav-child-items{
display: block;
}
.nav-page{
display: block;
position: relative;
padding: 5px 0 5px 20px;
color: #333;
font-weight: normal;
line-height: 1.5;
cursor: pointer;
font-weight: 600;
}
.nav-page:hover {
color: #005FE0;
background-color: rgba(236, 242, 252, 0.25);
}
.nav-page.active,
.nav-page.router-link-active{
color: #005FE0;
background-color: rgba(236,242,252,0.2);
}
.nav-page.active:after,
.nav-page.router-link-active:after{
display: inline-block;
}
.nav-page.active:hover,
.nav-page.router-link-active:hover{
color: #3F536E;
}
.nav-component{
display: block;
position: relative;
padding: 3px 0px 3px 27px;
font-size: 12px;
color: #575d6c;
font-family: "Comic Sans MS";
z-index: 2;
}
.nav-component:hover{
color: #005FE0;
background-color: rgba(236, 242, 252, 0.25);
}
.nav-component.active,
.nav-component.router-link-active{
color: #005FE0;
background-color: rgba(236, 242, 252, 0.25);
}
.nav-component.router-link-active .svg-promotion{
display: inline-block;
}
.nav-component span{
padding-left: 6px;
font-size: 13px;
}
.nav-item.active .icon-chevron-down{
transform: rotate(180deg);
transform-origin: center;
}
.icon-chevron-down{
display: inline-block;
text-indent: 0;
pointer-events: none;
position: absolute;
right: 10px;
top: 12px;
width: 16px;
height: 16px;
line-height: 16px;
transition: transform .3s cubic-bezier(.645,.045,.355,1);
}
.icon-chevron-down svg{
width: 16px;
height: 16px;
}
.icon-chevron-down svg path{
fill: #575d6c;
}
.svg-promotion{
display: inline-block;
height: 1em;
width: 1em;
line-height: normal;
fill: #1a6fe3;
position: absolute;
top: 9px;
left: 10px;
display: none;
}
</style>
编写index.vue
<template>
<div class="page">
<PageHeader class="page-header"></PageHeader>
<div class="page-content">
<div class="sidebar">
<pageSidebar></pageSidebar>
</div>
<div class="md-warp">
<Content />
</div>
</div>
<pageFooter class="page-footer"></pageFooter>
</div>
</template>
<script setup lang="ts">
import PageHeader from './header.vue'
import pageFooter from './footer.vue'
import pageSidebar from './sidebar.vue'
</script>
<style scoped>
.page{
width: 100%;
height: 100%;
overflow: hidden
}
.page-content {
position: relative;
display: flex;
background: #ebeff2;
height: calc(100% - 70px)
}
.page-content>.sidebar {
position: relative;
display: inline-block;
border-right: 1px solid #ebeff2;
color: #3f536e;
width: 190px;
flex-shrink: 0;
height: 100%;
background: #fff;
transition: all .3s;
}
.page-content>.md-warp{
position: relative;
padding: 15px;
flex: 1;
padding: 0;
background: #ebeff2;
z-index: 1;
overflow: auto;
}
.md-warp>div{
position: relative;
padding: 15px;
}
</style>
整体效果如下
结语
本文从实战出发,在前篇一个为 turbo的基础项目工程项目基础下,搭建vitePress,本文我估计,是全网唯一一个手把手第一次真正从0到一的完整的教程,纯属个人见解,因为我没有看到像我这么全的!,本文旨意在搭建一个vue3的组件库,后面还有更多的文章信息,我也不知道后面文章什么时候更新,本人很赖!希望大家鼓励鼓励我!