vue 实现分页效果
实现分页的基本思路
在Vue中实现分页效果通常需要结合后端API或前端数据分页逻辑。核心步骤包括计算总页数、处理当前页数据变更、渲染分页按钮等。
基于前端数据的分页实现
假设已有全部数据需在前端分页,可通过计算属性动态截取当前页数据:

<template>
<div>
<ul>
<li v-for="item in paginatedData" :key="item.id">{{ item.name }}</li>
</ul>
<div class="pagination">
<button @click="prevPage" :disabled="currentPage === 1">上一页</button>
<span>{{ currentPage }} / {{ totalPages }}</span>
<button @click="nextPage" :disabled="currentPage === totalPages">下一页</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
dataList: [], // 全部数据
currentPage: 1,
itemsPerPage: 10
}
},
computed: {
totalPages() {
return Math.ceil(this.dataList.length / this.itemsPerPage)
},
paginatedData() {
const start = (this.currentPage - 1) * this.itemsPerPage
const end = start + this.itemsPerPage
return this.dataList.slice(start, end)
}
},
methods: {
nextPage() {
if (this.currentPage < this.totalPages) this.currentPage++
},
prevPage() {
if (this.currentPage > 1) this.currentPage--
}
}
}
</script>
结合后端API的分页实现
当数据量较大时,通常需要后端配合返回分页数据:
<template>
<!-- 同上 -->
</template>
<script>
export default {
data() {
return {
paginatedData: [],
currentPage: 1,
totalPages: 0
}
},
mounted() {
this.fetchData()
},
methods: {
async fetchData() {
const res = await axios.get('/api/data', {
params: { page: this.currentPage }
})
this.paginatedData = res.data.items
this.totalPages = res.data.totalPages
},
nextPage() {
this.currentPage++
this.fetchData()
},
prevPage() {
this.currentPage--
this.fetchData()
}
}
}
</script>
高级分页组件实现
可封装更完善的分页组件,支持页码跳转和自定义样式:

<template>
<div class="pagination">
<button @click="changePage(1)" :disabled="currentPage === 1">首页</button>
<button @click="changePage(currentPage - 1)" :disabled="currentPage === 1">上一页</button>
<template v-for="page in displayedPages" :key="page">
<button
@click="changePage(page)"
:class="{ active: page === currentPage }"
>
{{ page }}
</button>
</template>
<button @click="changePage(currentPage + 1)" :disabled="currentPage === totalPages">下一页</button>
<button @click="changePage(totalPages)" :disabled="currentPage === totalPages">末页</button>
</div>
</template>
<script>
export default {
props: {
currentPage: Number,
totalPages: Number,
maxVisibleButtons: {
type: Number,
default: 5
}
},
computed: {
displayedPages() {
const half = Math.floor(this.maxVisibleButtons / 2)
let start = Math.max(1, this.currentPage - half)
let end = Math.min(this.totalPages, start + this.maxVisibleButtons - 1)
if (end - start + 1 < this.maxVisibleButtons) {
start = Math.max(1, end - this.maxVisibleButtons + 1)
}
return Array.from({ length: end - start + 1 }, (_, i) => start + i)
}
},
methods: {
changePage(page) {
if (page >= 1 && page <= this.totalPages) {
this.$emit('page-changed', page)
}
}
}
}
</script>
<style>
.pagination button {
margin: 0 5px;
}
.pagination button.active {
background-color: #42b983;
color: white;
}
</style>
使用第三方分页组件
现有UI库如Element Plus、Ant Design Vue等已提供成熟分页组件:
<!-- Element Plus -->
<el-pagination
v-model:currentPage="currentPage"
:page-size="10"
:total="100"
layout="prev, pager, next"
/>
<!-- Ant Design Vue -->
<a-pagination
v-model:current="currentPage"
:total="100"
show-less-items
/>
分页性能优化建议
对于大数据量场景,推荐使用无限滚动(Infinite Scroll)替代传统分页。可通过监听滚动事件动态加载数据:
<template>
<div class="infinite-list" @scroll="handleScroll">
<div v-for="item in visibleItems" :key="item.id">
{{ item.content }}
</div>
<div v-if="loading" class="loading">加载中...</div>
</div>
</template>
<script>
export default {
data() {
return {
allItems: [],
visibleItems: [],
loading: false,
batchSize: 20
}
},
methods: {
handleScroll(e) {
const { scrollTop, clientHeight, scrollHeight } = e.target
if (scrollHeight - (scrollTop + clientHeight) < 50 && !this.loading) {
this.loadMore()
}
},
loadMore() {
this.loading = true
// 模拟异步加载
setTimeout(() => {
const newItems = this.allItems.slice(
this.visibleItems.length,
this.visibleItems.length + this.batchSize
)
this.visibleItems = [...this.visibleItems, ...newItems]
this.loading = false
}, 500)
}
}
}
</script>






