【无标题】前端如何实现分页?

news2025/5/27 12:43:55

前端如何实现分页?

以下是对代码的逐条总结与解释,按 HTML、JavaScript、CSS 顺序分模块列出,每条代码单独说明:

一、HTML 代码解释

1. 表格容器
html
<table class="table table-bordered table-hover">
  1. 作用:定义表格,应用 Bootstrap 样式。
  2. 说明:
    class=“table”:基础表格样式。
    class=“table-bordered”:显示表格边框。
    class=“table-hover”:鼠标悬停时行高亮。
2. 表格表头
html
<thead>
    <tr>
        <th>选择</th>
        <th>头像</th>
        <th>用户名</th>
        <th>邮箱</th>
        <th>性别</th>
        <th>状态</th>
        <th>操作</th>
    </tr>
</thead>
  1. 作用:定义表格列标题。
  2. 说明:
    <th>:表头单元格,加粗居中显示,标识各列数据类型。
3. 表格主体
html
<tbody id="postList">
    <!-- 数据动态加载 -->
</tbody>
  1. 作用:动态加载数据的容器。
  2. 说明:
    id=“postList”:供 JavaScript 选择和操作,初始为空。
4. 分页导航容器

html

<div id="pageNav" class="pagination justify-content-center"></div>
  1. 作用:生成分页按钮的容器。
  2. 说明:
    id=“pageNav”:JavaScript 动态生成按钮的目标元素。
    class=“pagination”:Bootstrap 分页样式。
    justify-content-center:分页导航居中对齐。

二、JavaScript 代码解释

1. 初始化与全局变量
javascript
$(document).ready(function() {
    const rowsPerPage = 4; // 每页显示4条,与后端pageSize一致
    const $tableBody = $('#postList'); // 选择表格主体
    const $pageNav = $('#pageNav'); // 选择分页容器
    let currentPage = 1; // 当前页码
    let totalPages = 1; // 总页数,初始为1
    loadPage(1); // 加载第一页数据
});
  1. 作用:页面加载后初始化变量并加载数据。
  2. 说明:
    rowsPerPage:前端每页显示数量,需与后端一致。
    $tableBody 和 $pageNav:通过 id 选择 DOM 元素。
    currentPage 和 totalPages:跟踪分页状态。
    loadPage(1):触发第一页数据加载。
2. 数据加载函数 loadPage
javascript
function loadPage(pageNum) {
    currentPage = pageNum; // 更新当前页码
    $tableBody.html('<tr><td colspan="7" class="text-center">加载中...</td></tr>'); // 显示加载状态
    $.ajax({
        type: 'GET', // GET请求
        url: '/admin/getUsersFromManagerWithPaging', // 后端分页接口
        data: { pageNum, pageSize: rowsPerPage }, // 传递页码和每页大小
        success: function(response) { // 成功回调
            const userList = response.list || []; // 当前页数据(默认空数组)
            totalPages = response.totalPage || 1; // 总页数(默认1页)

            $tableBody.empty(); // 清空旧数据
            if (userList.length > 0) { // 有数据时渲染
                userList.forEach(user => { // 遍历生成表格行
                    const row = $('<tr>')
                        .attr('data-user-id', user.id) // 存储用户ID
                        .append(/* 7个单元格,填充数据 */); // 生成各列内容
                    $tableBody.append(row); // 添加行到表格
                });
                $pageNav.show(); // 显示分页导航
            } else { // 无数据时显示提示
                $tableBody.html('暂无用户数据');
                $pageNav.hide();
            }

            updatePagination(); // 更新分页按钮状态
        },
        error: function(error) { // 错误处理
            console.error('加载失败:', error);
            $tableBody.html('加载失败,请重试');
            $pageNav.hide();
        }
    });
}
  1. 作用:向后端请求数据并渲染到表格。
  2. 说明:
    $.ajax:发送异步请求获取分页数据。
    response.list:当前页用户列表,response.totalPage:总页数。
    $tableBody.empty():避免新旧数据叠加。
    updatePagination():根据数据更新分页导航。
3. 分页导航更新函数 updatePagination
javascript
function updatePagination() {
    $pageNav.empty(); // 清空旧按钮

    // 上一页按钮
    const prevBtn = $('<li class="page-item">')
        .append($('<a class="page-link">').text('上一页'));
    if (currentPage === 1) prevBtn.addClass('disabled'); // 首页禁用
    else prevBtn.click(() => loadPage(currentPage - 1)); // 非首页绑定点击事件
    $pageNav.append(prevBtn); // 添加到导航

    // 计算可见页码范围(最多5个)
    const maxVisiblePages = 5;
    let startPage = Math.max(1, currentPage - 2); // 起始页(当前页-2,最小1)
    let endPage = Math.min(totalPages, startPage + 4); // 结束页(起始页+4,最大总页数)

    // 左侧省略号
    if (startPage > 1) $pageNav.append('...');

    // 生成页码按钮
    for (let i = startPage; i <= endPage; i++) {
        const btn = $('<li class="page-item">')
            .append($('<a class="page-link">').text(i));
        if (i === currentPage) btn.addClass('active'); // 当前页高亮
        else btn.click(() => loadPage(i)); // 其他页绑定点击事件
        $pageNav.append(btn);
    }

    // 右侧省略号
    if (endPage < totalPages) $pageNav.append('...');

    // 下一页按钮
    const nextBtn = $('<li class="page-item">')
        .append($('<a class="page-link">').text('下一页'));
    if (currentPage === totalPages) nextBtn.addClass('disabled'); // 尾页禁用
    else nextBtn.click(() => loadPage(currentPage + 1)); // 非尾页绑定点击事件
    $pageNav.append(nextBtn); // 添加到导航
}
  1. 作用:动态生成分页按钮,更新按钮状态。
  2. 说明:
    maxVisiblePages = 5:最多显示 5 个页码,当前页居中。
    startPage 和 endPage:计算可见页码范围,避免超出总页数。
    disabled 类:禁用不可点击的按钮(如首页的 “上一页”)。
    active 类:高亮当前页按钮。

三、CSS 代码解释

1. 分页导航间距
css
.pagination {
    margin-top: 20px;
}
  1. 作用:在分页导航上方添加 20px 间距,避免紧贴表格。
  2. 说明:提升页面布局美观度,增加呼吸感。
2. 头像图片样式
css
.table img {
    object-fit: cover;
}
  1. 作用:确保头像图片在固定尺寸内完整显示,裁剪多余部分。
  2. 说明:避免图片拉伸变形,保持比例,适合头像展示。
3. 静态按钮样式
css
.static {
    border: none;
    background: transparent;
    cursor: default;
}
  1. 作用:将状态按钮设为静态文本,不可点击。
  2. 说明:
    border: none 和 background: transparent:移除按钮默认样式。
    cursor: default:鼠标样式为默认,明确非交互性。
4. 操作按钮间距
css
.deletebtn, .editbtn {
    margin-right: 5px;
}
  1. 作用:在 “删除” 和 “编辑” 按钮右侧添加 5px 间距。
  2. 说明:避免按钮紧贴,提升点击准确性和视觉舒适度。
<table class="table table-bordered table-hover">
    <thead>
        <tr>
            <th>选择</th>
            <th>头像</th>
            <th>用户名</th>
            <th>邮箱</th>
            <th>性别</th>
            <th>状态</th>
            <th>操作</th>
        </tr>
    </thead>
    <tbody id="postList">
        <!-- 数据将通过 AJAX 动态加载 -->
    </tbody>
</table>

<!-- 分页导航 -->
<div id="pageNav" class="pagination justify-content-center"></div>
$(document).ready(function() {
    const rowsPerPage = 4;
    const $tableBody = $('#postList'); // 选择正确的 tbody ID
    const $pageNav = $('#pageNav');
    let currentPage = 1;
    let totalPages = 1;

    // 初始化加载第一页
    loadPage(1);

    // 加载指定页数据
    function loadPage(pageNum) {
        currentPage = pageNum;
        $tableBody.html('<tr><td colspan="7" class="text-center">加载中...</td></tr>');

        $.ajax({
            type: 'GET',
            url: '/admin/getUsersFromManagerWithPaging',
            data: { pageNum, pageSize: rowsPerPage },
            success: function(response) {
                console.log('后端返回数据:', response);
                const userList = response.list || [];
                totalPages = response.totalPage || 1;

                $tableBody.empty();
                if (userList.length > 0) {
                    userList.forEach(user => {
                        const row = $('<tr>')
                            .attr('data-user-id', user.id)
                            .append(
                                $('<td>').html(`<input type="checkbox" class="rowCheckbox" data-user-id="${user.id}">`),
                                $('<td>').html(`<img alt="${user.username}" src="${user.avatarUrl || 'https://picsum.photos/200/150'}" class="img-thumbnail" style="width: 50px; height: 50px;">`),
                                $('<td>').text(user.username),
                                $('<td>').text(user.email),
                                $('<td>').text(user.gender || '未知'), // 确保字段存在
                                $('<td>').html(`<button class="static">${user.status}</button>`),
                                $('<td>').html(`
                                    <button class="deletebtn btn btn-danger btn-sm" data-user-id="${user.id}">删除</button>
                                    <button class="editbtn btn btn-primary btn-sm" data-user-id="${user.id}">编辑</button>
                                `)
                            );
                        $tableBody.append(row);
                    });
                    $pageNav.show();
                } else {
                    $tableBody.html('<tr><td colspan="7" class="text-center">暂无用户数据</td></tr>');
                    $pageNav.hide();
                }

                updatePagination();
            },
            error: function(error) {
                console.error('分页数据加载失败:', error);
                $tableBody.html('<tr><td colspan="7" class="text-center">加载失败,请重试</td></tr>');
                $pageNav.hide();
            }
        });
    }

    // 更新分页导航
    function updatePagination() {
        $pageNav.empty();

        // 上一页按钮
        const prevBtn = $('<li class="page-item">')
            .append($('<a class="page-link" href="#">').text('上一页'));
        if (currentPage === 1) {
            prevBtn.addClass('disabled');
        } else {
            prevBtn.click(function(e) {
                e.preventDefault();
                loadPage(currentPage - 1);
            });
        }
        $pageNav.append(prevBtn);

        // 页码按钮
        const maxVisiblePages = 5;
        let startPage = Math.max(1, currentPage - Math.floor(maxVisiblePages / 2));
        let endPage = Math.min(totalPages, startPage + maxVisiblePages - 1);

        if (startPage > 1) {
            $pageNav.append($('<li class="page-item disabled">').append($('<a class="page-link" href="#">').text('...')));
        }

        for (let i = startPage; i <= endPage; i++) {
            const pageBtn = $('<li class="page-item">')
                .append($('<a class="page-link" href="#">').text(i));
            if (i === currentPage) {
                pageBtn.addClass('active');
            } else {
                pageBtn.click(function(e) {
                    e.preventDefault();
                    loadPage(i);
                });
            }
            $pageNav.append(pageBtn);
        }

        if (endPage < totalPages) {
            $pageNav.append($('<li class="page-item disabled">').append($('<a class="page-link" href="#">').text('...')));
        }

        // 下一页按钮
        const nextBtn = $('<li class="page-item">')
            .append($('<a class="page-link" href="#">').text('下一页'));
        if (currentPage === totalPages) {
            nextBtn.addClass('disabled');
        } else {
            nextBtn.click(function(e) {
                e.preventDefault();
                loadPage(currentPage + 1);
            });
        }
        $pageNav.append(nextBtn);
    }
});
css
.pagination {
    margin-top: 20px;
}

.table img {
    object-fit: cover;
}

.static {
    border: none;
    background: transparent;
    cursor: default;
}

.deletebtn, .editbtn {
    margin-right: 5px;
}
@ApiOperation("用户分页")
    @ResponseBody
    @GetMapping("/getUsersFromManagerWithPaging")
    public Map<String,Object> getUsersFromManagerWithPaging(@RequestParam(value = "pageNum",defaultValue = "1")int pageNum,
                                                            @RequestParam(value = "pageSize",defaultValue = "4")int pageSize){
        PageInfo<User> pageInfo =adminService.getUsersFromManagerWithPaging(pageNum, pageSize);
        List<User> list = pageInfo.getList();
        Map<String,Object> response=new HashMap<>();
        if(list.isEmpty()){
            response.put("info","暂无用户");
        }
        response.put("list",list);
        response.put("totalPage",pageInfo.getPages());
        return response;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2386753.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【自然语言处理与大模型】大模型Agent四大的组件

大模型Agent是基于大型语言模型构建的智能体&#xff0c;它们能够模拟独立思考过程&#xff0c;灵活调用各类工具&#xff0c;逐步达成预设目标。这类智能体的设计旨在通过感知、思考与行动三者的紧密结合来完成复杂任务。下面将从大模型大脑&#xff08;LLM&#xff09;、规划…

小巧高效的目录索引生成软件

软件介绍 本文介绍的软件名为Snap2html&#xff0c;是一款树形目录索引生成工具。 软件大小与便捷性 Snap2html这款软件已完成汉化&#xff0c;其体积仅170kb&#xff0c;小巧无比&#xff0c;且无需安装&#xff0c;可直接投入使用。 软件使用方法 该软件操作简便&#xf…

云原生架构设计相关原则

文章目录 前言云原生架构概述云原生架构的核心原则一切皆服务原则自动化原则韧性和容错原则可观测性原则 云原生架构原则的实践意义 前言 大家好&#xff0c;我是沛哥儿。今天想和大家深入探讨一下云原生架构的相关原则。在如今数字化飞速发展的时代&#xff0c;云原生架构已经…

华为云Flexus+DeepSeek征文 | Flexus X实例助力 Dify-LLM 一键部署:性能跃升与成本优化的革新实践

引言 在AI大模型应用快速普及的背景下&#xff0c;企业对低门槛部署、高性能算力与成本可控的需求日益迫切。华为云推出的Flexus X实例&#xff0c;作为专为AI工作负载优化的新一代算力底座&#xff0c;通过1.6倍算力提升、关键业务6倍加速、综合降本30%等核心优势&#xff0c…

数据库blog7_MySql的下载与配置准备

&#x1f33f;MySql下载 &#x1f342;1.应用版本选择 选择社区版&#xff0c;免费适合初学者 相关链接下载页面下载界面介绍 &#x1f342;2.OS版本选择 根据自己的OS类型&#xff08;Windows/Linux&#xff08;CentOS/Ubuntu …&#xff09;/macOS&#xff09;选择对应版本…

YOLOv11助力地铁机场安检!!!一键识别刀具

文末有完整代码出处 随着现代社会的高速发展&#xff0c;交通工具和公共场所的安全管理面临着前所未有的挑战。尤其在机场、地铁、车站等公共安全检查点&#xff0c;如何提高安检效率、精准识别危险物品&#xff0c;成为了亟待解决的问题。在传统的安检过程中&#xff0c;X光图…

RFID工业读写器的场景化应用选型指南

RFID工业读写器是上海岳冉RFID专为工业场景设计的高性能射频识别设备&#xff0c;核心功能围绕高效数据采集与可靠传输展开。其基础能力包括多协议支持&#xff08;如ISO 18000-6C&#xff09;与多标签防碰撞处理&#xff0c;可同时读取/写入EPC编码、用户数据等标签信息&#…

单片机如何快速实现查看实时数据

在用 Keil 做调试的时候&#xff0c;最让人头秃的是什么&#xff1f; 不是写代码的BUG&#xff0c;而是&#xff1a;这个条件变量是什么情况&#xff1f;为什么没进入这个判断&#xff1f;我代码跑到哪里了&#xff1f; 其实本质上都是通过变量判断代码的执行顺序有没有问题 …

go实现钉钉三方登录

钉钉的的官方开发文档中只给出了java实现三方登录的&#xff0c;我们准备用go语言来实现 实现网页方式登录应用&#xff08;登录第三方网站&#xff09; - 钉钉开放平台 首先就是按照文档进行操作&#xff0c;备注好网站的信息 获得应用凭证&#xff0c;我们后面会用到 之后…

物流配送优化实战:用遗传算法破解选址难题

在电商与供应链高速发展的今天&#xff0c;物流配送成本优化始终是企业竞争力的核心议题之一。想象一下&#xff0c;当你面对 20 个分布在不同坐标的客户点、7 个可选配送中心和 1 个发件网点时&#xff0c;如何用最省钱的方式完成配送&#xff1f;今天我们就来拆解一个真实的物…

Linux 个人用户设置账号密码环境变量,四种方式

一、需要明白以下2点&#xff1a; 1、Linux 的环境变量是保存在变量 PATH 中&#xff0c;可通过 Linux shell 命令 echo $PATH 查看输出内容&#xff0c;或者直接输入 export 查看&#xff0c;或者输入 env 查看 2、Linux环境变量值之间是通过冒号进行隔开的( : ) 格式为&am…

Three.js搭建小米SU7三维汽车实战(5)su7登场

汽车模型加载 我们在sktechfab上下载的汽车是glb的文件格式&#xff0c;所以使用gltfLoader进行加载。这里将小车直接加载进来看看效果&#xff1b; import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js"; ....其余代码省略 const gltfLoader new GLT…

格恩朗管段超声波流量计:流量测量先锋

在流量测量技术不断迭代的浪潮中&#xff0c;格恩朗自 2019 年创立起&#xff0c;便以开拓者的姿态投身其中&#xff0c;致力于为全球用户提供先进、精准的流量测量解决方案。其旗下的管段超声波流量计&#xff0c;一经推出&#xff0c;便迅速吸引了行业的目光&#xff0c;成为…

图论 判断是否有环

前言&#xff1a;有点忘记是怎么判断一个图中是否是有环 如果是一个无向图&#xff0c;其实可以直接dfs&#xff0c;加上一个vis数组来一起判断 如果是有向图呢&#xff0c; class Solution:def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool…

EasyDarwin的配置与使用

一.语言配置 准备go语言 All releases - The Go Programming Language 增加系统环境变量 让其生效 二.项目配置 Clone项目并解压 git clone https://github.com/EasyDarwin/EasyDarwin.git cd EasyDarwin go mod tidy 紧接着 make build/linux cd build cd EasyDarwin-lin-&qu…

【Android】基于SurfaceControlViewHost实现跨进程渲染

1 前言 本文将介绍基于 SurfaceControlViewHost 实现跨进程渲染普通 View 和 GlSurfaceView&#xff0c;力求用最简单的 Demo&#xff0c;介绍 SurfaceControlViewHost 的应用&#xff0c;方便读者轻松扣出核心代码应用到自己的业务中。 核心代码片段如下。 1&#xff09;服务端…

vue+ThreeJs 创造自动选择的甜甜圈(圆环)

嗨&#xff0c;我是小路。今天主要和大家分享的主题是“vueThreeJs 创造自动选择的甜甜圈”。 一个漂浮在页面中央的 3D 圆环&#xff0c;多个图标/文本/图片均匀分布在圆周上。它会自动缓慢旋转&#xff0c;形成动态视觉焦点。这就是今天要搭建的项目&#xff0c;并对…

能说一下JVM的内存区域吗

根据Java虚拟机的规范&#xff0c;JVM的内存区域可以细分为程序计数器、虚拟机栈、本地方法栈、堆和方法区。 其中方法区和线程是共享的&#xff0c;虚拟机栈、本地方法区和程序计数器是线程私有的。 介绍一下程序计数器&#xff1f; 程序计数器也被称为PC寄存器。是一块较小…

东方仙盟_灵颜妙手——表单样式——仙盟创梦IDE

代码 .东方仙盟_灵颜妙手 {background-color: #f0f8ff;padding: 10px;display: block;width:100%;height: 100%;}.东方仙盟_灵颜妙手 .表单 {max-width: 800px;margin: 0 auto;background-color: white;border-radius: 8px;box-shadow: 0 0 10px rgba(0, 123, 255, 0.1);paddin…

输入一串字符,统计其中字母的个数

#include <stdio.h> int main() { char ch; int count 0; printf("请输入一串字符&#xff1a;\n"); while ((ch getchar())! \n) { if ((ch > a && ch < z) || (ch > A && ch < Z)) { count; } } printf("字母的个数为&a…