vue实现分页组件
Vue 分页组件实现
基础分页组件代码
以下是一个基于 Vue 3 的分页组件实现,包含基本功能和样式:
<template>
<div class="pagination">
<button
@click="changePage(currentPage - 1)"
:disabled="currentPage === 1"
>
上一页
</button>
<button
v-for="page in displayedPages"
:key="page"
@click="changePage(page)"
:class="{ active: currentPage === page }"
>
{{ page }}
</button>
<button
@click="changePage(currentPage + 1)"
:disabled="currentPage === totalPages"
>
下一页
</button>
</div>
</template>
<script>
export default {
props: {
totalItems: {
type: Number,
required: true
},
itemsPerPage: {
type: Number,
default: 10
},
currentPage: {
type: Number,
default: 1
},
maxVisibleButtons: {
type: Number,
default: 5
}
},
computed: {
totalPages() {
return Math.ceil(this.totalItems / this.itemsPerPage)
},
displayedPages() {
const range = []
const half = Math.floor(this.maxVisibleButtons / 2)
let start = Math.max(this.currentPage - half, 1)
let end = Math.min(start + this.maxVisibleButtons - 1, this.totalPages)
if (end - start + 1 < this.maxVisibleButtons) {
start = Math.max(end - this.maxVisibleButtons + 1, 1)
}
for (let i = start; i <= end; i++) {
range.push(i)
}
return range
}
},
methods: {
changePage(page) {
if (page >= 1 && page <= this.totalPages) {
this.$emit('page-changed', page)
}
}
}
}
</script>
<style>
.pagination {
display: flex;
justify-content: center;
gap: 5px;
margin-top: 20px;
}
.pagination button {
padding: 5px 10px;
border: 1px solid #ddd;
background: #fff;
cursor: pointer;
}
.pagination button:hover:not(:disabled) {
background: #eee;
}
.pagination button.active {
background: #007bff;
color: white;
border-color: #007bff;
}
.pagination button:disabled {
cursor: not-allowed;
opacity: 0.5;
}
</style>
组件使用示例
<template>
<div>
<!-- 列表数据渲染 -->
<ul>
<li v-for="item in paginatedItems" :key="item.id">
{{ item.name }}
</li>
</ul>
<!-- 分页组件 -->
<Pagination
:total-items="items.length"
:items-per-page="itemsPerPage"
:current-page="currentPage"
@page-changed="handlePageChange"
/>
</div>
</template>
<script>
import Pagination from './Pagination.vue'
export default {
components: {
Pagination
},
data() {
return {
items: [], // 从API获取的数据
itemsPerPage: 10,
currentPage: 1
}
},
computed: {
paginatedItems() {
const start = (this.currentPage - 1) * this.itemsPerPage
const end = start + this.itemsPerPage
return this.items.slice(start, end)
}
},
methods: {
handlePageChange(page) {
this.currentPage = page
// 可选: 这里可以添加API调用获取新页数据
}
},
async created() {
// 获取初始数据
// this.items = await fetchItems()
}
}
</script>
高级功能扩展
- 添加省略号表示更多页码
<template>
<div class="pagination">
<button @click="changePage(1)" :disabled="currentPage === 1">首页</button>
<button @click="changePage(currentPage - 1)" :disabled="currentPage === 1">上一页</button>
<template v-if="startPage > 1">
<button @click="changePage(1)">1</button>
<span v-if="startPage > 2">...</span>
</template>
<button
v-for="page in displayedPages"
:key="page"
@click="changePage(page)"
:class="{ active: currentPage === page }"
>
{{ page }}
</button>
<template v-if="endPage < totalPages">
<span v-if="endPage < totalPages - 1">...</span>
<button @click="changePage(totalPages)">{{ totalPages }}</button>
</template>
<button @click="changePage(currentPage + 1)" :disabled="currentPage === totalPages">下一页</button>
<button @click="changePage(totalPages)" :disabled="currentPage === totalPages">末页</button>
</div>
</template>
- 与API集成
methods: {
async changePage(page) {
if (page >= 1 && page <= this.totalPages) {
this.currentPage = page
try {
const response = await axios.get('/api/items', {
params: {
page,
per_page: this.itemsPerPage
}
})
this.items = response.data.items
this.totalItems = response.data.total
} catch (error) {
console.error('获取数据失败:', error)
}
}
}
}
- 响应式设计优化
@media (max-width: 600px) {
.pagination {
flex-wrap: wrap;
}
.pagination button {
margin-bottom: 5px;
}
.pagination span {
display: none;
}
}
注意事项
- 确保在父组件中正确处理
page-changed事件 - 当数据量变化时,可能需要重置当前页码为1
- 对于大型数据集,考虑使用服务器端分页而非客户端分页
- 可以通过props传递自定义样式类名实现更灵活的样式控制







