vue实现图库页面
实现图库页面的基本思路
使用Vue实现图库页面需要结合组件化开发、数据管理和UI交互。核心包括图片数据管理、布局渲染、交互功能(如预览、分页)等。以下是具体实现方法:
数据准备与组件结构
创建Gallery.vue作为主组件,定义图片数据数组,每个图片对象包含id、src、title等属性。数据可存储在组件的data中或通过Vuex/Pinia管理。
// Gallery.vue
data() {
return {
images: [
{ id: 1, src: '/path/to/image1.jpg', title: 'Image 1' },
{ id: 2, src: '/path/to/image2.jpg', title: 'Image 2' }
]
}
}
图片列表渲染
使用v-for指令循环渲染图片,结合CSS Grid或Flexbox实现响应式布局。为每张图片添加点击事件触发预览功能。
<template>
<div class="gallery-container">
<div
v-for="image in images"
:key="image.id"
class="gallery-item"
@click="openPreview(image)"
>
<img :src="image.src" :alt="image.title">
</div>
</div>
</template>
/* 响应式网格布局 */
.gallery-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 16px;
}
.gallery-item img {
width: 100%;
height: auto;
object-fit: cover;
}
图片预览功能
通过v-model控制预览模态框的显示状态,点击图片时将当前图片数据传入预览组件。
<template>
<image-preview
v-model="showPreview"
:current-image="currentImage"
/>
</template>
<script>
export default {
methods: {
openPreview(image) {
this.currentImage = image;
this.showPreview = true;
}
}
}
</script>
分页加载
结合v-infinite-scroll插件或手动监听滚动事件实现懒加载。计算分页参数并动态请求数据。
// 分页逻辑示例
loadMore() {
if (this.loading) return;
this.loading = true;
fetchImages(this.page++).then(data => {
this.images.push(...data);
this.loading = false;
});
}
优化与扩展
- 图片懒加载:使用
Intersection Observer API或v-lazy-image插件 - 动画效果:添加
transition-group实现布局变化动画 - 分类筛选:通过计算属性实现按标签过滤
- 响应式断点:使用CSS媒体查询调整网格列数
// 分类筛选示例
computed: {
filteredImages() {
return this.images.filter(img =>
this.selectedCategory ? img.category === this.selectedCategory : true
);
}
}
完整组件示例
<template>
<div>
<!-- 分类筛选 -->
<div class="filters">
<button @click="selectedCategory = null">All</button>
<button
v-for="cat in categories"
:key="cat"
@click="selectedCategory = cat"
>
{{ cat }}
</button>
</div>
<!-- 图片网格 -->
<div
class="gallery-grid"
v-infinite-scroll="loadMore"
>
<div
v-for="img in filteredImages"
:key="img.id"
class="gallery-item"
>
<img
:src="img.thumbnail"
@click="openLightbox(img)"
loading="lazy"
>
</div>
</div>
<!-- 预览模态框 -->
<lightbox
v-if="showLightbox"
:image="currentImage"
@close="showLightbox = false"
/>
</div>
</template>
<script>
export default {
data() {
return {
images: [],
page: 1,
loading: false,
selectedCategory: null,
showLightbox: false,
currentImage: null
}
},
computed: {
categories() {
return [...new Set(this.images.map(img => img.category))];
},
filteredImages() {
return this.selectedCategory
? this.images.filter(img => img.category === this.selectedCategory)
: this.images;
}
},
methods: {
async loadMore() {
if (this.loading) return;
this.loading = true;
const newImages = await fetchImages(this.page);
this.images.push(...newImages);
this.page++;
this.loading = false;
},
openLightbox(img) {
this.currentImage = img;
this.showLightbox = true;
}
}
}
</script>






