通过前面的努力, 我们已经封装了第一个表格组件, 但是我们还没有实现分页的功能.
分页这个功能在web开发中属于比较常见的了, 我们最好不要和table组件放一块, 可以单独封装一下.
那么我们直接开开搞吧.
基础分页首先我们在App.vue里面添加分页的元素:
<div class="page"> <ul> <li>上一页</li> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>下一页</li> </ul> </div>
此时还比较丑:
在这里插入图片描述我们美化一下样式, 让其实现居中对齐, 充满科技感的分页效果.
<script setup>import zdp_table1 from "./zdpui/components/zdp_table1.vue";import random from "./zdpui/js/random.js";const columns = [ { title: "员工编号", key: "id", width: 80, align: "center" }, { title: "姓名", key: "name", width: 100, align: "center" }, { title: "年龄", key: "age", width: 100, align: "center" }]const data = random.users(3)</script><template> <div> <zdp_table1 :columns="columns" :data="data" /> <div class="page"> <ul> <li>首页</li> <li>上一页</li> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>下一页</li> <li>末页</li> </ul> </div> </div></template><style scoped>.page { width: fit-content; margin: 0 auto; display: flex; justify-content: center; align-items: center;}.page ul { list-style-type: none; padding: 0; margin: 0; display: flex;}.page ul li { margin: 0 10px; padding: 10px 20px; cursor: pointer; border-radius: 5px; color: #fff; transition: all 0.3s ease; /* 使用线性渐变作为背景 */ background: linear-gradient(to bottom, #00A8FF, #0088cc);}.page ul li:hover { /* 悬停时使用更亮的渐变 */ background: linear-gradient(to bottom, #00C8FF, #00A8FF); box-shadow: 0 0 10px rgba(0, 168, 255, 0.8); transform: translateY(-2px);}.page ul li:active { /* 点击时使用稍暗的渐变 */ background: linear-gradient(to bottom, #0088cc, #0066aa); box-shadow: 0 0 5px rgba(0, 102, 170, 0.8) inset; transform: scale(0.95);}</style>
这个时候界面渲染效果如下, 美观多了.
在这里插入图片描述封装分页组件接下来就把分页相关的功能封装到一个组件中, 这样便于独立的维护和复用.
处于分页也可能有多种分页的考虑,我决定封装一个zdp_page1这样的组件.
此时, 我的项目结构如下:
在这里插入图片描述界面的渲染效果还是原来那样, 很完美, 此时App.vue完整代码如下:
<script setup>import zdp_table1 from "./zdpui/components/zdp_table1.vue";import zdp_page1 from "./zdpui/components/zdp_page1.vue";import random from "./zdpui/js/random.js";const columns = [ { title: "员工编号", key: "id", width: 80, align: "center" }, { title: "姓名", key: "name", width: 100, align: "center" }, { title: "年龄", key: "age", width: 100, align: "center" }]const data = random.users(3)</script><template> <div> <zdp_table1 :columns="columns" :data="data" /> <zdp_page1/> </div></template>
完善分页组件当前的分页组件过于简单了, 不支持传参, 也不支持监听点击事件, 我们来优化一下.
首先, 在分页的样式文件里面加一种激活时的样式:
.page1 ul li.active { background-color: #FF4500; background-image: linear-gradient(rgb(5, 39, 175), rgb(30, 60, 200)); color: white;}
接着调整分页组件的代码:
<script setup>import {ref, computed} from 'vue';import "../css/page.css";// 接收外部传入的当前页、每页数量和总数据量const props = defineProps({ page: { type: Number, default: 1, }, size: { type: Number, default: 8, }, total: { type: Number, default: 100, }});// 计算总页数const totalPage = computed(() => Math.ceil(props.total / props.size));// 计算可见的分页按钮数字const visiblePages = computed(() => { let start = Math.max(1, props.page - 2); let end = Math.min(totalPage.value, props.page + 2); let pages = []; for (let i = start; i <= end; i++) pages.push(i) return pages;});// 触发点击事件,更新当前页并发出事件const emit = defineEmits(['change']);const goToPage = (page) => { if (page < 1) page = 1; if (page > totalPage.value) page = totalPage.value; emit('change', page);};</script><template> <div class="page1"> <ul> <li @click="goToPage(1)">首页</li> <li @click="goToPage(page - 1)">上一页</li> <!-- 显示当前页前两页和后两页 --> <li v-for="v in visiblePages" :key="v" :class="{ active: v === page }" @click="goToPage(v)" > {{ v }} </li> <li @click="goToPage(page + 1)">下一页</li> <li @click="goToPage(totalPage)">末页</li> </ul> </div></template>
修改一下App.vue, 使用这个分页组件:
<script setup>import zdp_table1 from "./zdpui/components/zdp_table1.vue";import zdp_page1 from "./zdpui/components/zdp_page1.vue";import random from "./zdpui/js/random.js";import {ref} from "vue";const columns = [ { title: "员工编号", key: "id", width: 80, align: "center" }, { title: "姓名", key: "name", width: 100, align: "center" }, { title: "年龄", key: "age", width: 100, align: "center" }]const data = random.users(3)const page = ref(1);const size = ref(10);const total = ref(100);const onChangePage = (v) => page.value = v</script><template> <div> <zdp_table1 :columns="columns" :data="data" /> <zdp_page1 :page="page" :size="size" :total="total" @change="onChangePage" /> </div></template>
此时分页的效果就更加的好看了, 而且点击的时候会动态切换分页.
在这里插入图片描述不过我们分页变化以后, 数据并没有跟着变化, 我们继续完善一下代码.
数据随着分页改变要实现数据随着分页改变, 最简单的方式就是分页变化以后, 重新生成随机的用户数据.
const page = ref(1);const size = ref(10);const total = ref(100);const data = ref(random.users(size.value))const onChangePage = (v) => { page.value = v data.value = random.users(size.value)}
这个时候每次点击分页, 可以发现数据都会变化, 但是前面的id并没有跟着变.
那么该怎么解决这个id没有跟着变化的问题呢?
我想到的一个解决方案就是增强随机数据模块, 提供一个根据分页获取随机用户信息的方法. 这个方法返回的是一个对象, 对象中用total标记总共有多少条数据, 用data存储当前页的数据.
解决id不变的问题在随机模块中增加一个分页获取用户信息的方法:
function getPageUser( page = 1, size = 8, total = 888,){ const startIndex = (page - 1) * size; const endIndex = startIndex + size; const result = []; let id = startIndex + 1; for (let i = startIndex; i < endIndex && i < total; i++) { result.push({ id: id++, name: name(), age: age() }); } return { total: total, data: result };}
修改App.vue, 分页获取用户数据:
<script setup>import zdp_table1 from "./zdpui/components/zdp_table1.vue";import zdp_page1 from "./zdpui/components/zdp_page1.vue";import random from "./zdpui/js/random.js";import {ref} from "vue";const columns = [ { title: "员工编号", key: "id", width: 80, align: "center" }, { title: "姓名", key: "name", width: 100, align: "center" }, { title: "年龄", key: "age", width: 100, align: "center" }]const page = ref(1);const size = ref(10);const total = ref(100);const data = ref(random.users(size.value))const onChangePage = (v) => { page.value = v const newData = random.getPageUser( page.value, size.value, ) data.value = newData.data total.value = total.value}</script><template> <div> <zdp_table1 :columns="columns" :data="data" /> <zdp_page1 :page="page" :size="size" :total="total" @change="onChangePage" /> </div></template>
此时, 界面就会随着分页的变化而动态变化了.
在这里插入图片描述总结现在我们已经实现了一个基本的分页组件, 这个分页组件可以监听分页的点击事件, 动态的根据分页请求后端的数据.
虽然我们现在是模拟的, 但是当我们接入后端数据的那一刻, 会发现一切都是如此的简单.
那么接下来要继续开发什么呢?
我们还缺什么?
我们缺一个插槽的功能, 这个插槽应该能够实现操作相关的东西, 比如删除用户, 编辑用户等等, 用户也可以自定义扩展这个插槽, 实现自己的逻辑.
那么, 让我们继续开搞吧!!!