#
VitePress真是太好用了
2026-02-23
图片轮播组件开发
详细介绍如何开发一个高性能的图片轮播组件ImageGallery,用于在VitePress中展示图片集。涵盖组件需求分析、Vue3+TypeScript代码实现、组件注册方法、响应式布局与暗色模式适配、箭头切换与缩略图导航等核心功能的完整开发流程。
概述
本文介绍如何开发一个高性能的图片轮播组件 ImageGallery,用于在 VitePress 中展示图片集。
组件需求
- 大图展示(圆角矩形,与 BiliVideo 风格一致)
- 底部缩略图列表
- 鼠标悬停大图显示左右箭头切换
- 图片自动缩放填满框
- 支持本地图片和图链
- 轻量快速,不影响加载速度
组件代码
创建文件 docs/.vitepress/theme/components/ImageGallery.vue:
<script setup lang="ts">
import { ref } from 'vue'
interface Props {
images: {
src: string
alt?: string
}[]
}
const props = defineProps<Props>()
const activeIndex = ref(0)
const showArrows = ref(false)
const prev = () => {
activeIndex.value = activeIndex.value === 0 ? props.images.length - 1 : activeIndex.value - 1
}
const next = () => {
activeIndex.value = activeIndex.value === props.images.length - 1 ? 0 : activeIndex.value + 1
}
</script>
<template>
<div v-if="images && images.length > 0" class="image-gallery">
<div
class="main-image"
@mouseenter="showArrows = true"
@mouseleave="showArrows = false"
>
<img
:src="images[activeIndex].src"
:alt="images[activeIndex].alt || 'gallery image'"
/>
<div v-if="images.length > 1" class="arrow arrow-left" :class="{ visible: showArrows }" @click="prev">
<svg viewBox="0 0 24 24" width="24" height="24">
<path fill="currentColor" d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>
</svg>
</div>
<div v-if="images.length > 1" class="arrow arrow-right" :class="{ visible: showArrows }" @click="next">
<svg viewBox="0 0 24 24" width="24" height="24">
<path fill="currentColor" d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/>
</svg>
</div>
</div>
<div class="thumbnails">
<div
v-for="(img, index) in images"
:key="index"
class="thumbnail"
:class="{ active: index === activeIndex }"
>
<img :src="img.src" :alt="img.alt || `thumbnail ${index}`" />
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.image-gallery {
width: 100%;
margin: 1.5rem 0;
}
.main-image {
width: 100%;
position: relative;
padding-bottom: 56.25%;
border-radius: 12px;
overflow: hidden;
background: var(--vp-c-bg-soft);
box-shadow: 0 0 20px rgba(255, 255, 255, 0);
@media (prefers-color-scheme: dark) {
box-shadow: 0 0 20px rgba(255, 255, 255, 0.1), 0 0 10px rgba(255, 255, 255, 0.2);
}
img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
}
.arrow {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.5);
color: white;
border-radius: 50%;
cursor: pointer;
opacity: 0;
transition: opacity 0.3s ease;
&.visible {
opacity: 1;
}
&:hover {
background: rgba(0, 0, 0, 0.7);
}
svg {
width: 24px;
height: 24px;
}
}
.arrow-left {
left: 10px;
}
.arrow-right {
right: 10px;
}
.thumbnails {
display: flex;
gap: 10px;
margin-top: 12px;
justify-content: center;
flex-wrap: wrap;
}
.thumbnail {
width: 80px;
height: 60px;
border-radius: 8px;
overflow: hidden;
opacity: 0.5;
transition: all 0.3s ease;
border: 2px solid transparent;
cursor: pointer;
&:hover {
opacity: 0.8;
}
&.active {
opacity: 1;
border-color: var(--vp-c-brand);
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
@media (max-width: 640px) {
.thumbnail {
width: 60px;
height: 45px;
}
.arrow {
width: 32px;
height: 32px;
svg {
width: 20px;
height: 20px;
}
}
}
</style>注册组件
在 docs/.vitepress/theme/index.ts 中注册组件:
import ImageGallery from "./components/ImageGallery.vue";
export default {
enhanceApp({ app }: { app: any }) {
app.component('ImageGallery', ImageGallery);
},
};使用方法
在 Markdown 文件中使用:
<ImageGallery :images="[
{ src: '图片1地址.jpg', alt: '图片1' },
{ src: '图片2地址.jpg', alt: '图片2' },
{ src: '图片3地址.jpg', alt: '图片3' }
]" />关键实现点
1. 类型定义
使用 TypeScript 接口定义图片数组结构:
interface Props {
images: {
src: string
alt?: string
}[]
}2. 图片填充
使用 padding-bottom 百分比实现响应式 16:9 容器:
.main-image {
padding-bottom: 56.25%; // 16:9 比例
}
img {
object-fit: cover; // 图片填满容器
}3. 箭头切换
使用 v-if 控制箭头显示,通过点击事件切换图片:
const showArrows = ref(false)
const prev = () => {
activeIndex.value = activeIndex.value === 0 ? props.images.length - 1 : activeIndex.value - 1
}4. 暗色模式适配
使用 CSS 变量和媒体查询适配暗色模式:
@media (prefers-color-scheme: dark) {
box-shadow: 0 0 20px rgba(255, 255, 255, 0.1), 0 0 10px rgba(255, 255, 255, 0.2);
} 本文由 DoubleSpirit121 原创
采用 CC BY-NC-SA 4.0 协议进行许可
TAGS:
VitePress 1.6.3
0 评论