Mysql 实现移动端滑动分页

本文介绍了一种在数据库中实现游标分页的方法,通过存储过程和Laravel/Lumen框架进行封装,适用于移动端滑动分页的需求。文章详细解释了存储过程的创建和调用流程,以及如何在Laravel/Lumen中使用封装好的类进行分页操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

很多移动端分页功能是滑动分页,当 api 需要提供分页功能的时候,数据库端需要使用 procedure 存储过程.

1. 使用 workbench 或其他的数据库操作工具新建储存过程

将新建的存储过程命名为 paging

新建存储过程代码 

CREATE DEFINER=`dev_pmall`@`%` PROCEDURE `paging`(IN tb_name    VARCHAR(128), IN select_str VARCHAR(1024), IN where_str VARCHAR(1024),
                        IN where_str2 VARCHAR(1024), IN order_by_str VARCHAR(1024), IN counter INT)
BEGIN
    SET @current = 0;
    SET @row_number = 0;

    SET @sql1 = CONCAT('SELECT t2.row_number into @current
    FROM
      (SELECT
         (@row_number := @row_number + 1) AS row_number,
         t.*
       FROM (SELECT * FROM ', tb_name, ') t
       WHERE ', where_str, '
       ORDER BY ', order_by_str, '
      ) t2
    WHERE ', where_str2, ' ;');
    PREPARE sql1 FROM @sql1;
    EXECUTE sql1;

    SET @row_number = 0;
    SET @sql2 = CONCAT('SELECT ', select_str, '
    FROM
      (SELECT
         (@row_number := @row_number + 1) AS row_number,
         t.*
       FROM (SELECT * FROM ', tb_name, ') t
       WHERE ', where_str, '
       ORDER BY', order_by_str, '
      ) t2
    WHERE t2.row_number > ', @current, ' LIMIT 0, ', counter, ';');
    PREPARE sql2 FROM @sql2;
    EXECUTE sql2;

  END

封装的存储过程使用类(Laravel/Lumen 框架)

<?php
    /**
     * Created by PhpStorm.
     * User: nwei
     * Date: 2018/6/7
     * Time: 12:05
     *
     *    .--,       .--,
     *   ( (  \.---./  ) )
     *    '.__/o   o\__.'
     *       {=  ^  =}
     *        >  -  <
     *       /       \
     *      //       \\
     *     //|   .   |\\
     *     "'\       /'"_.-~^`'-.
     *        \  _  /--'         `
     *      ___)( )(___
     *     (((__) (__)))    高山仰止,景行行止.虽不能至,心向往之.
     *
     */


    namespace App\Tools;


    use Illuminate\Support\Facades\DB;

    class CursorPaging {

            protected $table_name = null;
            protected $select_str = null;
            protected $where_str = null;
            protected $where_str2 = null;
            protected $order_by_str = null;
            protected $since = null;
            protected $count = null;

        /**
         * CursorPaging constructor.
         * @param $table_name
         * @param $select_str
         * @param $where_str
         * @param $where_str2
         * @param $order_by_str
         * @param $since
         * @param $count
         *
         *  通过 pop 商城存储过程修改,该 pop 使用 CI 框架,代表 sql 示例
         *
         *  if ($sec['since']) {
                $query = $this->db2->query("
                CALL `paging`(
                ' {$tb_name} ',
                ' product_id,name,sub_name,status,image,pd_price,stocks ',
                ' status = 1 and device = 2 and name like ''%{$keyword}%'' ',
                ' product_id = {$sec['since']} ',
                ' date_added desc, product_id desc ',
                {$sec['count']}
                );");
            } else {
                $query = $this->db2
                ->select('product_id,name,sub_name,status,image,pd_price,stocks')
                ->where('status', 1)
                ->where('device', 2)
                ->like('name', $keyword)
                ->order_by('date_added desc, product_id desc')
                ->limit($sec['count'], 0)
                ->get('v_wx_product');
            }
 *
         *
         *  未集成前示例
         *
            if ($since) {
            $tb_name = "sms";
            $select_str = "*";
            $where_str = "1=1"; //条件
            $where_str2 = " id = ".$since; //游标条件
            $order_by_str = " id desc ";
            $counter = $count;

            $rs = DB::select('call paging(?, ?, ?, ?,?,?)',[$tb_name,$select_str,$where_str,$where_str2,$order_by_str,$counter]);

            } else {
                $query = "select * from sms order by id desc limit 0,".env("COUNT");
                $rs = DB::select($query);
            }
            return $this->jsonData("0","ok",$rs);
         *
         */
            function __construct($table_name,$select_str,$where_str,$where_str2,$order_by_str,$since,$count) {
                $this->since = isset($since)?$since:null;
                $this->count = isset($count)?$count:env("COUNT"); //选填
                $this->table_name = $table_name; //必填
                $this->select_str = isset($select_str)?$select_str:"*";
                $this->where_str = isset($where_str)?$where_str:" 1=1 ";
                $this->where_str2 = $where_str2; //必填
                $this->order_by_str = $order_by_str; //必填

            }

        /**
         * 利用游标分页
         * @return mixed
         */
            public function cursor_paging(){
                $rs = null;
                if ($this->since) {

                    $params = [
                        $this->table_name,
                        $this->select_str,
                        $this->where_str,
                        $this->where_str2,
                        $this->order_by_str,
                        $this->count
                    ];

                    $rs = DB::select('call paging(?, ?, ?, ?,?,?)',$params);

                } else {

                    $query = "select ".$this->select_str." from ".$this->table_name." where ".$this->where_str." order by ".$this->order_by_str."  limit 0,".$this->count;

                    $rs = DB::select($query);
                }

                return $rs;

            }

    }

构造函数参数说明

构造函数中的第一个参数是表名,第二个参数是要查询的字段名,不传参默认为 '*',第三个参数是查询条件,不传参默认为 '1=1',第四个参数是游标条件,第五个参数是排序方式,第六个参数是开始游标,第七个参数为每页的数量.

使用示例

 public function getProducts($request,$product_type){
                    $since = !empty($request->input("since"))?$request->input("since"):null;
                    $where_str = " status = 1 and weight = 1 and product_type = ".$product_type ."  ";
                    $where_str2 = " id = ".$since ." ";
                    $order_by_str = " updated_at desc ";
                    $table_name = " product ";
                    $select_str = null;

                    $rs = [];
                    try{
                        $procedure = new CursorPaging($table_name,$select_str,$where_str,$where_str2,$order_by_str,$since,null);

                        $rs = $procedure->cursor_paging();
                      
                    }catch (\Exception $exception){
                        $rs = false;
                        operate_log("0","前端获取商品列表失败",$exception);
                    }

                    return $rs;

            }

结果

这是没有任何参数的请求结果, 每页两条数据,此时它的游标位在表中 id=1 的位置上,第二次请求时我们的路由应该变成这样

http://localhost:30017/api/v1/front/products?since=1

结果

这样的结果跟我们数据库的查询结果是一样的

 

### 切页滑动列表功能的实现 为了实现分页滑动效果,可以采用多种前端框架和技术栈来完成这一目标。以下是基于不同技术方案的具体说明: #### 使用 MUI 框架实现分页滑动效果 MUI 是一个轻量级的移动端 HTML5 UI 框架,适合用于构建移动应用界面。通过设置 `.mui-scrollbar` 的样式属性 `display: none !important;` 可以隐藏页面的垂直滚动条[^1]。这有助于优化用户体验并增强视觉一致性。 对于分页滑动效果,可以通过监听用户的上下拉动操作(即上拉加载更多数据和下拉刷新当前数据),结合异步请求动态更新数据列表。这种交互方式能够显著提升用户浏览体验。 #### Vue.js 结合 Element UI 或自定义组件实现分页器与滑动列表 如果选用 Vue.js 作为主要开发工具,则推荐搭配 Element UI 库中的 Pagination 组件来快速搭建分页机制[^2]。Element 提供了两个重要回调方法: - **size-change** 方法会在更改每页显示记录数量时被触发; - **current-change** 方法则负责处理切换到新页面的操作逻辑。 另外,在某些场景下可能需要更灵活的设计风格或者行为模式,这时就可以考虑引入类似于引用[3]提到的那种仿支付宝样式的可滑动轮播分页宫格菜单组件[^3]。它不仅支持常见的九宫格布局形式,还扩展到了十二宫格甚至十五宫格选项卡展示需求之上。 #### 数据库层面的支持 - SQL 查询语句配合 LIMIT 子句 无论采取哪种前端展现手段,最终都离不开后台数据库服务端给予的数据支撑作用。例如利用 MySQL 中非常实用的一个特性——LIMIT 关键字来进行高效的结果集截取工作[^4]。“SELECT * FROM table_name LIMIT offset, count;" 这样的语法结构允许开发者轻松指定起始位置(offset)以及希望获取的数量(count),从而达到按需加载的目的。 #### 面试技巧分享 值得注意的是,在实际求职过程中遇到关于此类话题探讨的时候,除了掌握上述理论知识点之外,还需要提前梳理好个人简历里提及的相关技能点及其背后蕴含的工作经历故事线[^5]。只有这样才能做到胸有成竹地应对考官提问,并且突出自己与众不同的优势所在。 ```javascript // 示例代码片段 (Vue + Axios 实现简单的分页功能) <template> <div class="pagination-container"> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page.sync="currentPage" :page-sizes="[10, 20, 30]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="totalCount"></el-pagination> </div> </template> <script> export default { data() { return { currentPage: 1, pageSize: 10, totalCount: 0, listData: [] }; }, methods: { handleSizeChange(val) { this.pageSize = val; this.fetchData(); }, handleCurrentChange(val) { this.currentPage = val; this.fetchData(); }, async fetchData() { const res = await axios.get('/api/data', { params: { page: this.currentPage, size: this.pageSize } }); this.listData = res.data.items; this.totalCount = res.data.total; } } }; </script> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值