VitePress全局组件封装
前言
VuePress
主题默认有 <CodeGroup>
组件用于切换代码很方便。
如图所示:
痛点
使用 VitePress
后,官方没有提供 <CodeGroup>
组件类似的方案。
参考 VuePress 源码
自己封装 CodeGroup
项目下新建全局组件:components\CodeGroup.vue
实现代码如下:
<template>
<ClientOnly>
<div class="theme-code-group">
<div class="theme-code-group__nav">
<ul class="theme-code-group__ul">
<li
v-for="(tab, i) in codeTabs"
:key="tab.title"
class="theme-code-group__li"
>
<button
class="theme-code-group__nav-tab"
:class="{
'theme-code-group__nav-tab-active': i === activeCodeTabIndex,
}"
@click="changeCodeTab(i)"
>
{{ tab.title }}
</button>
</li>
</ul>
</div>
<slot />
<pre v-if="codeTabs.length < 1" class="pre-blank"> // 没代码~ </pre>
</div>
</ClientOnly>
</template>
<script>
export default {
name: 'CodeGroup',
data() {
return {
codeTabs: [],
activeCodeTabIndex: -1,
}
},
watch: {
activeCodeTabIndex(index) {
this.activateCodeTab(index)
},
},
mounted() {
this.loadTabs()
},
methods: {
changeCodeTab(index) {
this.activeCodeTabIndex = index
},
async loadTabs() {
await this.$nextTick()
this.codeTabs = (this.$slots.default() || [])
.filter(slot => Boolean(slot.props))
.map((slot, index) => {
if (slot.props.active === '') {
this.activeCodeTabIndex = index
}
return {
title: slot.props.title,
elm: slot.el,
}
})
if (this.activeCodeTabIndex === -1 && this.codeTabs.length > 0) {
this.activeCodeTabIndex = 0
}
this.activateCodeTab(0)
},
activateCodeTab(index) {
this.codeTabs.forEach(tab => {
if (tab.elm) {
tab.elm.style.display = 'none'
}
})
if (this.codeTabs[index]?.elm) {
this.codeTabs[index].elm.style.display = 'block'
}
},
},
}
</script>
<style scoped>
/* .theme-code-group {} */
.theme-code-group__nav {
margin-bottom: -35px;
background-color: #282c34;
padding-bottom: 22px;
border-radius: 6px;
padding-left: 10px;
padding-top: 10px;
}
.theme-code-group__ul {
margin: auto 0;
padding-left: 0;
display: flex;
list-style: none;
}
.theme-code-group__li {
margin-top: 0;
margin-right: 10px;
}
.theme-code-group__nav-tab {
border: 0;
padding: 5px;
cursor: pointer;
background-color: transparent;
font-size: 0.85em;
line-height: 1.4;
color: rgba(255, 255, 255, 0.9);
font-weight: 600;
}
.theme-code-group__nav-tab-active {
border-bottom: #42b983 1px solid;
}
.pre-blank {
color: #42b983;
margin: 0;
}
</style>
全局注册组件
新建主题配置文件:docs\.vitepress\theme\index.js
VitePress
中注册全局组件:
import DefaultTheme from 'vitepress/theme'
import CodeGroup from '../../../components/CodeGroup.vue'
export default {
...DefaultTheme,
enhanceApp({ app }) {
app.component('CodeGroup', CodeGroup)
}
}
在 md 文档中使用
🚨注意:由于语法限制,以下代码统一缩进了一个 Tab 制表符,在使用时请删除 Tab 制表符。
# CodeGroup 自定义全局组件
## 测试 JS + TS
<CodeGroup>
<div title="ts" active>
```ts{2}
// 注释
const add = (a: number, b: number): number => {
return a + b
}
console.log(add(1, 2))
```
</div>
<div title="js">
```js{2}
// 注释
const add = (a, b) => {
return a + b
}
console.log(add(1, 2))
```
</div>
</CodeGroup>
## 测试 yarn + npm + pnpm
<CodeGroup>
<div title="yarn" active>
```sh
# install in your project
yarn add -D vitePress
```
</div>
<div title="npm">
```sh
# install in your project
npm install -D vitePress
```
</div>
<div title="pnpm">
```sh
# install in your project
pnpm install -D vitePress
```
</div>
</CodeGroup>