自定义组件
编写组件
本站点使用VuePress驱动,使用的主题是vuepress-theme-plume。
在docs/.vuepress/theme/components目录下编写组件。
例如,我编写一个名为SiteNavigation.vue的组件,用于展示自定义一个站点的推荐站点导航,组件的内容:
<script setup lang="ts">
import { ref, PropType } from "vue";
/**
* 站点数据结构定义
*/
interface SiteItem {
title: string; // 站点名称
icon: string; // 图标类名
href: string; // 站点链接
description: string; // 站点描述
}
/**
* 站点分类结构定义
*/
interface SiteCategory {
name: string; // 分类名称
sites: SiteItem[]; // 分类下的站点列表
}
/**
* SiteNavigation 组件属性定义
* @property categories - 站点分类列表
* @property columns - 每行显示的站点数量,默认为8
*/
const props = defineProps({
categories: {
type: Array as PropType<SiteCategory[]>,
required: true,
},
columns: {
type: Number,
default: 8,
},
});
</script>
<template>
<div class="site-navigation-container">
<div
v-for="(category, categoryIndex) in categories"
:key="categoryIndex"
class="site-category"
>
<h3 class="category-title">{{ category.name }}</h3>
<div class="site-grid" :style="{ '--columns': columns }">
<a
v-for="(site, siteIndex) in category.sites"
:key="siteIndex"
:href="site.href"
target="_blank"
rel="noopener noreferrer"
class="site-card"
>
<div class="site-icon">
<Icon :name="site.icon" size="2em" />
</div>
<div class="site-info">
<h4 class="site-title">{{ site.title }}</h4>
<p class="site-description">{{ site.description }}</p>
</div>
</a>
</div>
</div>
</div>
</template>
<style scoped>
.site-navigation-container {
width: 100%;
padding: 20px 50px;
}
.site-category {
margin-bottom: 32px;
}
.category-title {
font-size: 1.25rem;
font-weight: 600;
margin: 0 0 20px 0;
color: #2c3e50;
}
.site-grid {
display: grid;
grid-template-columns: repeat(var(--columns), 1fr);
gap: 12px;
}
.site-card {
display: flex;
flex-direction: row;
align-items: center;
padding: 12px 16px;
border: 1px solid #e8e8e8;
border-radius: 6px;
text-decoration: none;
color: inherit;
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
}
.site-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
border-color: #6AA1B7;
}
.site-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 3px;
height: 100%;
background: linear-gradient(180deg, #6AA1B7 0%, #67c23a 100%);
opacity: 0;
transition: opacity 0.25s ease;
}
.site-card:hover::before {
opacity: 1;
}
.site-icon {
width: 44px;
height: 44px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 12px;
border-radius: 6px;
background: linear-gradient(135deg, #f5f7fa 0%, #e8ecf1 100%);
flex-shrink: 0;
transition: all 0.25s ease;
}
.site-icon svg {
color: #6AA1B7;
transition: color 0.25s ease;
}
.site-card:hover .site-icon svg {
color: #ffffff;
}
.site-info {
flex: 1;
min-width: 0;
text-align: left;
}
.site-title {
font-size: 0.85rem;
font-weight: 600;
margin: 0 0 4px 0;
color: #2c3e50;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
transition: color 0.25s ease;
}
.site-description {
font-size: 0.7rem;
color: #7f8c8d;
margin: 0;
line-height: 1.3;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
min-height: 1.3em;
}
/* 响应式设计 */
@media (max-width: 1600px) {
.site-grid {
--columns: 6;
}
}
@media (max-width: 1200px) {
.site-grid {
--columns: 4;
}
.site-card {
padding: 14px 18px;
}
.site-icon {
width: 48px;
height: 48px;
margin-right: 14px;
}
.site-title {
font-size: 0.9rem;
}
.site-description {
font-size: 0.75rem;
}
}
@media (max-width: 768px) {
.site-grid {
--columns: 3;
gap: 10px;
}
.site-card {
padding: 12px 14px;
}
.site-icon {
width: 42px;
height: 42px;
margin-right: 10px;
}
.site-title {
font-size: 0.85rem;
}
.site-description {
font-size: 0.7rem;
-webkit-line-clamp: 1;
}
.category-title {
font-size: 1.15rem;
}
}
@media (max-width: 480px) {
.site-grid {
--columns: 2;
gap: 8px;
}
.site-card {
padding: 10px 12px;
}
.site-icon {
width: 36px;
height: 36px;
margin-right: 8px;
}
.site-title {
font-size: 0.8rem;
}
.site-description {
font-size: 0.65rem;
display: none;
}
.category-title {
font-size: 1.1rem;
}
}
</style>引入组件
在docs/.vuepress/client.ts文件中引入组件:
import SiteNavigation from "@/components/SiteNavigation.vue";
export default defineClientConfig({
enhance({ app }) {
app.component("SiteNavigation", SiteNavigation);
},
});使用组件
在需要使用组件的Markdown文件中,使用组件标签即可:
<SiteNavigation
:categories="[
{
name: '代码托管',
sites: [
{
title: '码云 Gitee',
icon: 'nimbus:link',
href: 'https://gitee.com/',
description: '国内领先的代码托管和协作平台'
},
{
title: 'GitHub',
icon: 'logos:github-icon',
href: 'https://github.com',
description: '全球最大的开源代码托管平台'
}
]
}
]"
:columns="6"
/>