# 如何實現Vue3封裝自己的分頁組件
## 前言
在Web開發中,分頁功能幾乎是所有數據展示場景的必備功能。雖然市面上有許多優秀的分頁組件庫(如Element Plus、Ant Design Vue等),但掌握自定義分頁組件的開發能力仍然非常重要。本文將詳細介紹如何使用Vue3從零開始封裝一個功能完善、可定制性強的分頁組件。
## 一、分頁組件需求分析
在開始編碼前,我們需要明確組件的基本功能需求:
1. **基礎功能**:
- 顯示頁碼按鈕
- 上一頁/下一頁導航
- 首頁/末頁快速跳轉
- 當前頁碼高亮顯示
- 禁用不可用按鈕(如第一頁時禁用"上一頁")
2. **擴展功能**:
- 支持自定義每頁顯示數量
- 支持跳轉到指定頁碼
- 支持顯示總頁數和總條數
- 支持不同尺寸和樣式定制
- 支持國際化
3. **交互需求**:
- 點擊頁碼觸發頁面切換
- 頁碼變化時觸發回調事件
## 二、項目初始化
首先創建一個Vue3項目(如果已有項目可跳過此步驟):
```bash
npm init vue@latest vue-pagination-demo
cd vue-pagination-demo
npm install
在src/components目錄下創建Pagination.vue文件:
<template>
<div class="pagination">
<!-- 分頁結構將在這里實現 -->
</div>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({
total: { type: Number, required: true }, // 總數據量
current: { type: Number, default: 1 }, // 當前頁碼
pageSize: { type: Number, default: 10 }, // 每頁條數
pageRange: { type: Number, default: 5 } // 顯示頁碼數量
})
const emit = defineEmits(['update:current', 'change'])
// 計算總頁數
const totalPages = computed(() => {
return Math.ceil(props.total / props.pageSize)
})
</script>
<style scoped>
.pagination {
display: flex;
justify-content: center;
align-items: center;
margin: 20px 0;
}
</style>
完善template部分:
<template>
<div class="pagination">
<button
:disabled="current <= 1"
@click="handlePageChange(current - 1)"
>
上一頁
</button>
<template v-for="page in pageList" :key="page">
<button
:class="{ active: page === current }"
@click="handlePageChange(page)"
>
{{ page }}
</button>
</template>
<button
:disabled="current >= totalPages"
@click="handlePageChange(current + 1)"
>
下一頁
</button>
<span class="page-info">
共 {{ totalPages }} 頁 / {{ total }} 條
</span>
</div>
</template>
在script部分添加計算屬性:
// 計算顯示的頁碼數組
const pageList = computed(() => {
const range = []
const halfRange = Math.floor(props.pageRange / 2)
let start = Math.max(1, props.current - halfRange)
let end = Math.min(totalPages.value, start + props.pageRange - 1)
// 調整起始位置確保顯示足夠頁碼
if (end - start + 1 < props.pageRange) {
start = Math.max(1, end - props.pageRange + 1)
}
for (let i = start; i <= end; i++) {
range.push(i)
}
return range
})
// 處理頁碼變化
const handlePageChange = (page) => {
if (page < 1 || page > totalPages.value || page === props.current) return
emit('update:current', page)
emit('change', page)
}
修改template部分:
<button
:disabled="current <= 1"
@click="handlePageChange(1)"
>
首頁
</button>
<!-- 原有頁碼按鈕 -->
<button
:disabled="current >= totalPages"
@click="handlePageChange(totalPages)"
>
末頁
</button>
添加跳轉輸入框:
<div class="page-jump">
跳至
<input
type="number"
v-model.number="jumpPage"
min="1"
:max="totalPages"
@keyup.enter="handleJump"
>
頁
</div>
添加相關邏輯:
const jumpPage = ref(null)
const handleJump = () => {
if (!jumpPage.value) return
handlePageChange(Math.max(1, Math.min(jumpPage.value, totalPages.value)))
jumpPage.value = null
}
添加選擇器:
<select v-model="localPageSize" @change="handlePageSizeChange">
<option value="10">10條/頁</option>
<option value="20">20條/頁</option>
<option value="50">50條/頁</option>
<option value="100">100條/頁</option>
</select>
添加相關邏輯:
const localPageSize = ref(props.pageSize)
const handlePageSizeChange = () => {
emit('update:pageSize', localPageSize.value)
// 切換每頁條數后重置到第一頁
handlePageChange(1)
}
.pagination button {
margin: 0 5px;
padding: 5px 10px;
border: 1px solid #ddd;
background: #fff;
cursor: pointer;
border-radius: 4px;
transition: all 0.3s;
}
.pagination button:hover:not(:disabled) {
background: #f0f0f0;
}
.pagination button:disabled {
color: #ccc;
cursor: not-allowed;
}
.pagination button.active {
background: #1890ff;
color: white;
border-color: #1890ff;
}
.page-info {
margin-left: 15px;
color: #666;
}
.page-jump {
margin-left: 15px;
}
.page-jump input {
width: 50px;
padding: 5px;
margin: 0 5px;
border: 1px solid #ddd;
border-radius: 4px;
text-align: center;
}
添加props:
size: {
type: String,
default: 'default',
validator: (value) => ['small', 'default', 'large'].includes(value)
}
添加size相關樣式:
.pagination.small button {
padding: 3px 7px;
font-size: 12px;
}
.pagination.large button {
padding: 7px 15px;
font-size: 16px;
}
<template>
<div>
<!-- 數據列表 -->
<ul>
<li v-for="item in currentData" :key="item.id">
{{ item.name }}
</li>
</ul>
<!-- 分頁組件 -->
<Pagination
v-model:current="currentPage"
:total="totalItems"
:page-size="pageSize"
@change="handlePageChange"
/>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
import Pagination from '@/components/Pagination.vue'
const totalItems = ref(100) // 模擬總數據量
const currentPage = ref(1)
const pageSize = ref(10)
// 模擬當前頁數據
const currentData = computed(() => {
const start = (currentPage.value - 1) * pageSize.value
const end = start + pageSize.value
return mockData.slice(start, end)
})
const handlePageChange = (page) => {
console.log('當前頁碼:', page)
// 這里可以添加獲取新數據的邏輯
}
</script>
添加語言配置:
const props = defineProps({
// ...其他props
locale: {
type: Object,
default: () => ({
prev: '上一頁',
next: '下一頁',
first: '首頁',
last: '末頁',
total: '共 {total} 條',
page: '頁',
jump: '跳至'
})
}
})
修改template中使用語言配置:
<button @click="handlePageChange(1)">
{{ locale.first }}
</button>
添加具名插槽支持:
<template v-for="page in pageList" :key="page">
<slot name="page" :page="page" :isActive="page === current">
<button :class="{ active: page === current }">
{{ page }}
</button>
</slot>
</template>
使用TransitionGroup實現切換動畫:
<TransitionGroup name="pagination" tag="div" class="pagination">
<!-- 分頁按鈕 -->
</TransitionGroup>
添加動畫樣式:
.pagination-move {
transition: transform 0.3s;
}
defineProps({
total: { type: Number, required: true },
current: { type: Number, default: 1 },
pageSize: { type: Number, default: 10 },
pageRange: { type: Number, default: 5 },
size: {
type: String,
default: 'default',
validator: (value) => ['small', 'default', 'large'].includes(value)
},
showTotal: { type: Boolean, default: true },
showJumper: { type: Boolean, default: true },
showSizeChanger: { type: Boolean, default: true },
locale: {
type: Object,
default: () => ({
prev: '上一頁',
next: '下一頁',
first: '首頁',
last: '末頁',
total: '共 {total} 條',
page: '頁',
jump: '跳至'
})
}
})
通過本文,我們完成了一個功能完善的Vue3分頁組件的開發過程。這個組件具有以下特點:
在實際項目中,你可以根據需求進一步擴展或調整這個組件。自定義組件的開發不僅能滿足特定業務需求,也是提升Vue技術水平的好方法。
完整組件代碼可參考GitHub倉庫:vue3-pagination-component
”`
這篇文章詳細介紹了Vue3分頁組件的開發過程,從需求分析到具體實現,再到功能擴展和樣式優化,最后到組件封裝與發布。全文約3400字,采用Markdown格式編寫,包含代碼示例和說明,適合中高級Vue開發者閱讀參考。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。