Vue3实现Pagination分页组件(三)自定义控件布局

转载自:Vue3实现Pagination分页组件(三)自定义控件布局 - 掘金

写在前面

在 B 端的 web 开发中,分页组件或者叫分页器,是较为常用的控件之一,通常配合表格或列表,实现数据量大的情况下,分页拆解数据的功能。

由于完整实现的篇幅较大,所以我分成了以下几部分逐个讲解,这里是第三讲:自定义控件布局,如果你需要查看完整的源代码实现,请访问Pagination 分页组件

  • 基础实现
  • 分页操作控件
  • 自定义控件布局
  • 限制最大页码数

需求拆分

由于分页组件包含有不少的小控件,包括prev 上一页、next-下一页、pager-页码、jumper-输入跳转、sizes-每页条数选择器、total-总条数;通常情况下,用户希望可以自主的选择需要展示的控件,以及它们的顺序,甚至可以自定义显示的文案。那么根据这些要求,则可以列出以下难点:

  • 如何定义用户传入的自定义配置?
  • 如何实现按需加载对应控件和顺序?
  • 组件的属性和事件触发如何处理?

定义用户传入配置

对于大多数流行组件库的分页组件而言,通用的做法是将组控件名以逗号链接的方式,作为属性传入,接收后解析需要加载的控件和顺序,这里使用的就是这个方案,例如:

layout: { type: String, default: "total,prev,pager,next", validator: layoutValidator }, // 自定义组件布局

/**
* 自定义布局配置验证
* @param {String} v
* @returns Boolean
*/
const layoutValidator = (v) => v.split(",").length !== 0;
复制代码

加载控件并渲染

先说下逻辑方面,我们获取了用户需要加载的控件之后,需要准备一个componentsList用于生成最后的列表以供<component> 组件遍历渲染,如下:

<template v-for="(item, index) in componentsList" :key="`p-${index}`">
    <component :is="item.component" v-bind="item.bind" @[item.event]="item.eventName"></component>
</template>
复制代码

根据上面我们可以确定,渲染需要包含组件以及bindeventeventName,用于绑定属性和动态处理事件名和回调方法。

这里以「上一页」Prev控件为例,定义该控件需要绑定的属性和事件

const prevComponents = computed(() => {
    return {
        bind: {
            text: props.prevText,
            disabled: props.disabled || currentPage.value === 1,
        },
        event: "click",
        eventName: setCurrentPage,
    };
});

// 以下省略
const nextComponents = ...
const totalComponents = ...
const sizesComponents = ...
const jumperComponents = ...
const pagerComponents = ...
复制代码

引入控件,并创建映射保存起来

import total from "./components/total.vue";
import prev from "./components/prev.vue";
import pager from "./components/pager.vue";
import next from "./components/next.vue";
import jumper from "./components/jumper.vue";
import sizes from "./components/sizes.vue";

const layout_map = { total, totalPages, prev, pager, next, jumper, sizes, simple };
复制代码

准备好数据后,便可以进行componentsList的组装:

// 返回一个包含组件模板、属性以及事件的组件列表
const componentsList = computed(() => {
    const { layout, simple } = props
    const layout_list = simple ? ["prev", "simple", "next"] : layout.split(","); // 可自定义的分页布局配置

    const components = [];

    // 各组件的属性以及事件配置
    const component_map = {
        total: totalComponents.value,
        totalPages: totalPagesComponents.value,
        prev: prevComponents.value,
        pager: pagerComponents.value,
        next: nextComponents.value,
        jumper: jumperComponents.value,
        sizes: sizesComponents.value,
        simple: simpleComponents.value,
    };

    layout_list.map((name) => {
        components.push({ name, component: layout_map[name], ...component_map[name] });
    });

    return components;
});
复制代码

欢迎


作者:木亦Sam
链接:https://juejin.cn/post/7082125256529281032
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3实现分页组件的步骤如下: 1. 创建Pagination组件 首先,我们需要创建Pagination组件,该组件包含以下内容: ``` <template> <div class="pagination"> <ul> <li v-if="currentPage > 1" @click="changePage(currentPage - 1)"> <a href="#">上一页</a> </li> <li v-for="index in pages" :key="index" :class="{ active: currentPage === index }" @click="changePage(index)"> <a href="#">{{ index }}</a> </li> <li v-if="currentPage < pageCount" @click="changePage(currentPage + 1)"> <a href="#">下一页</a> </li> </ul> </div> </template> <script> export default { name: "Pagination", props: { currentPage: { type: Number, default: 1, }, pageSize: { type: Number, default: 10, }, total: { type: Number, default: 0, }, }, computed: { pageCount() { return Math.ceil(this.total / this.pageSize); }, pages() { const pages = []; for (let i = 1; i <= this.pageCount; i++) { pages.push(i); } return pages; }, }, methods: { changePage(page) { if (page !== this.currentPage) { this.$emit("update:currentPage", page); } }, }, }; </script> <style> .pagination { display: flex; justify-content: center; margin-top: 20px; } .pagination ul { display: flex; list-style: none; padding: 0; margin: 0; } .pagination li { margin: 0 5px; } .pagination li a { display: block; padding: 5px 10px; text-decoration: none; color: #333; border-radius: 3px; transition: background-color 0.3s ease-in-out; } .pagination li.active a { background-color: #333; color: #fff; } </style> ``` 2. 在父组件中使用Pagination组件 在父组件中,我们需要将currentPage、pageSize和total属性传递给Pagination组件,并且监听Pagination组件的update:currentPage事件,以便在分页组件中改变当前页码时,更新父组件中的数据。 ``` <template> <div class="container"> <h1>分页组件</h1> <table> <thead> <tr> <th>姓名</th> <th>年龄</th> </tr> </thead> <tbody> <tr v-for="(item, index) in list" :key="index"> <td>{{ item.name }}</td> <td>{{ item.age }}</td> </tr> </tbody> </table> <Pagination :currentPage.sync="currentPage" :pageSize="pageSize" :total="total" /> </div> </template> <script> import Pagination from "./Pagination.vue"; export default { name: "App", components: { Pagination, }, data() { return { list: [ { name: "小明", age: 18, }, { name: "小红", age: 20, }, { name: "小张", age: 22, }, { name: "小李", age: 24, }, { name: "小王", age: 26, }, { name: "小刘", age: 28, }, { name: "小赵", age: 30, }, { name: "小钱", age: 32, }, { name: "小孙", age: 34, }, { name: "小周", age: 36, }, ], currentPage: 1, pageSize: 4, total: 10, }; }, computed: { dataList() { const start = (this.currentPage - 1) * this.pageSize; const end = start + this.pageSize; return this.list.slice(start, end); }, }, watch: { currentPage(val) { console.log(val); }, }, }; </script> <style> .container { max-width: 600px; margin: 0 auto; } table { width: 100%; border-collapse: collapse; } th, td { padding: 10px; text-align: left; border: 1px solid #ccc; } </style> ``` 3. 实现分页逻辑 在父组件中,我们需要根据当前页码和每页显示条数,计算出需要显示的数据,然后将其渲染到页面上。同时,我们需要监听Pagination组件的update:currentPage事件,以便在分页组件中改变当前页码时,更新父组件中的数据。 完整的代码如下: ``` <template> <div class="container"> <h1>分页组件</h1> <table> <thead> <tr> <th>姓名</th> <th>年龄</th> </tr> </thead> <tbody> <tr v-for="(item, index) in dataList" :key="index"> <td>{{ item.name }}</td> <td>{{ item.age }}</td> </tr> </tbody> </table> <Pagination :currentPage.sync="currentPage" :pageSize="pageSize" :total="total" /> </div> </template> <script> import Pagination from "./Pagination.vue"; export default { name: "App", components: { Pagination, }, data() { return { list: [ { name: "小明", age: 18, }, { name: "小红", age: 20, }, { name: "小张", age: 22, }, { name: "小李", age: 24, }, { name: "小王", age: 26, }, { name: "小刘", age: 28, }, { name: "小赵", age: 30, }, { name: "小钱", age: 32, }, { name: "小孙", age: 34, }, { name: "小周", age: 36, }, ], currentPage: 1, pageSize: 4, total: 10, }; }, computed: { dataList() { const start = (this.currentPage - 1) * this.pageSize; const end = start + this.pageSize; return this.list.slice(start, end); }, }, watch: { currentPage(val) { console.log(val); }, }, }; </script> <style> .container { max-width: 600px; margin: 0 auto; } table { width: 100%; border-collapse: collapse; } th, td { padding: 10px; text-align: left; border: 1px solid #ccc; } </style> ``` 以上就是Vue3实现分页组件的详细步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值