Vue3 分页组件使用指南与封装方法一、基础使用方法1. 安装依赖确保项目中已安装 Vue3 和 Tailwind CSS:
代码语言:bash复制npm install vue@3 tailwindcss@latest2. 创建分页组件将前面示例代码保存为 Pagination.vue 文件:
代码语言:javascript复制// Pagination.vue
{{ item.title }}
{{ item.content }}
import { ref, computed } from 'vue';
// 模拟数据
const mockData = Array.from({ length: 50 }, (_, i) => ({
id: i + 1,
title: `文章标题 ${i + 1}`,
content: `这是文章 ${i + 1} 的内容描述...`
}));
// 分页状态
const currentPage = ref(1);
const itemsPerPage = ref(10);
// 计算属性
const totalItems = computed(() => mockData.length);
const totalPages = computed(() => Math.ceil(totalItems.value / itemsPerPage.value));
// 当前页数据
const currentPageData = computed(() => {
const startIndex = (currentPage.value - 1) * itemsPerPage.value;
const endIndex = startIndex + itemsPerPage.value;
return mockData.slice(startIndex, endIndex);
});
// 可见页码范围
const visiblePages = computed(() => {
let startPage = Math.max(1, currentPage.value - 2);
let endPage = Math.min(totalPages.value, startPage + 4);
if (endPage - startPage < 4) {
startPage = Math.max(1, endPage - 4);
}
return Array.from({ length: endPage - startPage + 1 }, (_, i) => startPage + i);
});
// 分页操作
const goToPage = (page) => {
if (page >= 1 && page <= totalPages.value) {
currentPage.value = page;
}
};
const prevPage = () => {
if (currentPage.value > 1) {
currentPage.value--;
}
};
const nextPage = () => {
if (currentPage.value < totalPages.value) {
currentPage.value++;
}
};
.primary {
background-color: #3b82f6;
}
3. 在页面中使用在需要分页功能的组件中引入并使用:
代码语言:javascript复制
文章列表
import Pagination from './Pagination.vue';
二、组件封装方法1. 提取props使组件可复用将数据和分页配置作为 props 传入,使组件可以在不同场景复用:
代码语言:javascript复制// Pagination.vue
{{ item.title }}
{{ item.content }}
import { ref, computed, defineProps, defineEmits } from 'vue';
const props = defineProps({
data: {
type: Array,
required: true
},
itemsPerPage: {
type: Number,
default: 10
},
initialPage: {
type: Number,
default: 1
}
});
// 分页状态
const currentPage = ref(props.initialPage);
// 计算属性
const totalItems = computed(() => props.data.length);
const totalPages = computed(() => Math.ceil(totalItems.value / props.itemsPerPage));
// 当前页数据
const currentPageData = computed(() => {
const startIndex = (currentPage.value - 1) * props.itemsPerPage;
const endIndex = startIndex + props.itemsPerPage;
return props.data.slice(startIndex, endIndex);
});
// 可见页码范围
const visiblePages = computed(() => {
let startPage = Math.max(1, currentPage.value - 2);
let endPage = Math.min(totalPages.value, startPage + 4);
if (endPage - startPage < 4) {
startPage = Math.max(1, endPage - 4);
}
return Array.from({ length: endPage - startPage + 1 }, (_, i) => startPage + i);
});
// 分页操作
const goToPage = (page) => {
if (page >= 1 && page <= totalPages.value) {
currentPage.value = page;
}
};
const prevPage = () => {
if (currentPage.value > 1) {
currentPage.value--;
}
};
const nextPage = () => {
if (currentPage.value < totalPages.value) {
currentPage.value++;
}
};
.primary {
background-color: #3b82f6;
}
2. 添加事件回调添加页码变化时的回调事件,便于父组件处理:
代码语言:javascript复制// 新增emits定义
const emits = defineEmits(['page-change']);
// 在页码变化时触发事件
const goToPage = (page) => {
if (page >= 1 && page <= totalPages.value) {
currentPage.value = page;
emits('page-change', page); // 触发页码变化事件
}
};
// 同样处理prevPage和nextPage方法
const prevPage = () => {
if (currentPage.value > 1) {
currentPage.value--;
emits('page-change', currentPage.value);
}
};3. 使用插槽自定义内容添加插槽使列表内容可以自定义:
代码语言:javascript复制
{{ item.title }}
{{ item.content }}
三、高级使用示例1. 使用封装后的分页组件代码语言:javascript复制
商品列表
{{ item.name }}
{{ item.description }}
¥{{ item.price }}
加入购物车
import { ref, onMounted } from 'vue';
import Pagination from './Pagination.vue';
const products = ref([]);
onMounted(() => {
// 模拟从API获取商品数据
fetchProducts().then(data => {
products.value = data;
});
});
const fetchProducts = async () => {
// 实际项目中这里会是API调用
return [
{ id: 1, name: '商品1', price: 99.9, description: '这是一个很棒的商品', image: 'https://picsum.photos/200/300?random=1' },
{ id: 2, name: '商品2', price: 199.9, description: '高质量产品', image: 'https://picsum.photos/200/300?random=2' },
// 更多商品...
];
};
2. 监听页码变化事件代码语言:javascript复制 :data="products" :items-per-page="6" @page-change="handlePageChange" /> const handlePageChange = (page) => { console.log('当前页码:', page); // 可以在这里添加页面滚动到顶部等逻辑 window.scrollTo({ top: 0, behavior: 'smooth' }); }; 四、自定义配置选项1. 样式配置可以通过 props 传递自定义类名: 代码语言:javascript复制// 在组件中添加props const props = defineProps({ // 其他props保持不变 pageBtnClass: { type: String, default: 'w-10 h-10 flex items-center justify-center rounded-md transition-colors duration-200' }, activeBtnClass: { type: String, default: 'bg-primary text-white' }, inactiveBtnClass: { type: String, default: 'bg-gray-200 hover:bg-gray-300' } }); // 在模板中使用 2. 页码显示范围配置代码语言:javascript复制// 添加props visibleRange: { type: Number, default: 2 // 左右显示的页码数量 } // 更新计算属性 const visiblePages = computed(() => { let startPage = Math.max(1, currentPage.value - props.visibleRange); let endPage = Math.min(totalPages.value, startPage + props.visibleRange * 2); if (endPage - startPage < props.visibleRange * 2) { startPage = Math.max(1, endPage - props.visibleRange * 2); } return Array.from({ length: endPage - startPage + 1 }, (_, i) => startPage + i); });五、最佳实践建议保持组件单一职责:分页组件只负责分页逻辑,数据获取和渲染由父组件处理使用provide/inject:对于大型应用,可以使用 Vue 的 provide/inject 机制提供全局分页配置添加过渡动画:使用 Vue 的 transition 组件为页面切换添加平滑过渡效果考虑无障碍性:为分页按钮添加 aria-label 属性,提高屏幕阅读器的可用性单元测试:为分页逻辑编写单元测试,确保各种边界条件下的正确性通过以上封装方法,你可以创建一个高度可复用、灵活配置的分页组件,满足各种前端分页需求。 Vue3, 分页组件,前端开发,组件封装,JavaScript,TypeScript, 响应式设计,props,emit, 自定义事件,插槽,样式绑定,性能优化,SSR, 单元测试