Vue3封装分页组件

分页组件:

<template>
	<div class="paginationBox" :style="{justifyContent: alignPosition}">
        <el-pagination
            class="pagination"
            :current-page="currentPage"
            :page-size="pageSize"
            :page-sizes="pageSizes"
            :layout="layout"
            :total="total"
            :background="true"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
        />
    </div>
</template>

<script setup>
import { reactive, computed } from 'vue'
const props = defineProps({
    total: {
        required: true,
        type: Number,
        default: 0
    },
    // 当前页数
    currentPage: {
        required: true,
        type: Number,
        default: 1
    },
    // 分页
    pageSize: {
        required: true,
        type: Number,
        default: 10
    },
    //每页显示个数选择器的选项设置
    pageSizes: {
        type: Array,
        default: () => ([10, 20, 30, 50, 100])
    },
    layout: {
        type: String,
        default: 'total, sizes, prev, pager, next, jumper'
    },
    // 对齐方式
    align: { // left | center | right  居左、居中、居右
        type: String,
        default: 'right',
    },
});

const emit = defineEmits(['onChange']);

// 分页切换
const handleCurrentChange = (val)=>{
    emit('onChange', { currentPage: val, pageSize: props.pageSize });
}

// 每页数量切换
const handleSizeChange = (val)=>{
    emit('onChange', { currentPage: props.currentPage, pageSize: val });
}

// 对齐方式样式
const alignPosition = computed(() => {
    let cssCode = 'flex-end';
    switch (props.align) {
        case 'left':
            cssCode = 'flex-start';
            break;
        case 'center':
            cssCode = 'center';
            break;
        default:
            cssCode = 'flex-end';
            break;
    }
    return cssCode;
})

</script>

<style lang="scss" scoped>

.paginationBox {
	display: flex;
	align-items: center;
	justify-content: flex-end;
}
:deep(.pagination) {
    padding: 10px;
    button {
        border-radius: 50%;
        margin: 0 4px;
        width: 30px;
        height: 30px;
    }
    .el-pager {
        li {
            width: 30px;
            height: 30px;
            line-height: 30px;
            border-radius: 50%;
            margin: 0 4px;
            color: #757B92;
            &.is-active {
                border: 1px solid #006EFF;
                background: #006EFF;
                box-shadow: 0 0 10px 0#6268FF;
                color: #ffffff;
                font-weight: normal;
            }
        }
    }
}
</style>

调用:

// HTML
<Pagination 
	:current-page="paginationData.currentPage"
	:page-size="paginationData.pageSize"
	:total="paginationData.total"
	@onChange="paginationData.onChange"
/>

// Js
const paginationData = reactive({
	currentPage:1,
	pageSize: 10,
	total: 0,
	onChange: ({currentPage, pageSize}) => {
		paginationData.currentPage = currentPage;
		paginationData.pageSize = pageSize;
        //请求接口
		getList();
	},
})

效果:

### 封装 Vue 3 和 TypeScript 的分页组件 为了创建一个功能齐全且易于使用的分页组件,在 Vue 3 中使用 TypeScript 可以为开发人员提供更好的类型安全性和代码提示支持。下面是一个详细的实现方案。 #### 组件结构设计 定义 `Pagination` 组件来处理页面切换逻辑以及样式展示等功能。此组件接收一些属性作为配置项,比如总条目数、每页显示数量等,并通过这些参数计算出总的页码数目[^1]。 #### 属性说明 | 参数名 | 类型 | 默认值 | 描述 | | --- | --- | --- | --- | | totalItems | number | - | 数据总量 | | pageSize | number | 10 | 每一页显示多少条记录 | | currentPage | number | 1 | 当前选中的页码 | #### 实现代码示例 以下是基于上述描述编写的简单版分页器: ```typescript <template> <nav aria-label="Page navigation"> <ul class="pagination justify-content-center"> <!-- 上一页按钮 --> <li :class="{ disabled: currentPage === 1 }" @click="prevPage()"> <a href="#" tabindex="-1">上一页</a> </li> <!-- 数字页码列表 --> <li v-for="(page, index) in pagesList" :key="index" :class="{ active: page === currentPage }" @click="changePage(page)"> <a>{{ page }}</a> </li> <!-- 下一页按钮 --> <li :class="{ disabled: currentPage >= totalPages }" @click="nextPage()"> <a>下一页</a> </li> </ul> </nav> </template> <script setup lang="ts"> import { computed, defineProps, ref } from &#39;vue&#39;; interface Props { totalItems?: number; pageSize?: number; } const props = withDefaults(defineProps<Props>(), { totalItems: 0, pageSize: 10, }); // 计算总共有几页 const totalPages = computed(() => Math.ceil(props.totalItems / props.pageSize)); // 定义当前页状态变量,默认第一页 let currentPage = ref<number>(1); // 动态生成要渲染的页码数组 const pagesList = computed(() => Array.from({ length: totalPages.value }, (_, i) => i + 1) ); function changePage(newPage: number): void { if (newPage !== currentPage.value && newPage > 0 && newPage <= totalPages.value) { currentPage.value = newPage; emit(&#39;update:currentPage&#39;, newPage); } } function prevPage(): void { const nextPage = currentPage.value - 1; changePage(nextPage); } function nextPage(): void { const nextPage = currentPage.value + 1; changePage(nextPage); } </script> ``` 该模板部分展示了带有上下翻页链接和中间具体页码链接的一组导航控件;脚本则负责监听用户的交互操作并更新相应的视图数据[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值