hsbolg

手写前端分页组件

服务端接口开发

Mybatis-PageHelper

  • 个人理解

    Mybatis-PageHelper的原理是通过AOP在截获我们执行的SQL的时候,再执行一次SQL语句,填充到返回值里

  • 使用方法

    在pom.xml中添加相关依赖

    <!-- mybatis pager -->
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>4.1.0</version>
    </dependency>
    
    <dependency>
      <groupId>com.github.miemiedev</groupId>
      <artifactId>mybatis-paginator</artifactId>
      <version>1.2.17</version>
    </dependency>
    
    <dependency>
      <groupId>com.github.jsqlparser</groupId>
      <artifactId>jsqlparser</artifactId>
      <version>0.9.4</version>
    </dependency>
    

在applicationContext-datasource.xml文件中添加相关配置,设置方言为mysql

<!-- 分页插件 -->
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageHelper">
                    <property name="properties">
                        <value>
                            dialect=mysql
                        </value>
                    </property>
                </bean>
            </array>
        </property>

在ProductController.java的list接口添加如下配置,对于不是必传的搜索字段,要置成false,因为在RqquestParam.class注解中规定了default true,即使自己在搜索的时候,不传关键字,require也一定要置为false。动态分页需要用到两个参数pageNumpageSize

 @RequestMapping("list.do")
    @ResponseBody
    public ServerResponse<PageInfo> list(@RequestParam(value = "keyword",required = false)String keyword,
                                         @RequestParam(value = "categoryId",required = false)Integer categoryId,
                                         @RequestParam(value = "pageNum",defaultValue = "1") int pageNum,
                                         @RequestParam(value = "pageSize",defaultValue = "10")int pageSize,
                                         @RequestParam(value = "orderBy",defaultValue = "")String orderBy){
        return iProductService.getProductByKeywordCategory(keyword, categoryId, pageNum, pageSize, orderBy);
    }

在ProductServiceImpl.java接口实现中,添加如下配置

public ServerResponse<PageInfo> getProductByKeywordCategory(String keyword,Integer categoryId,int pageNum,int pageSize,String orderBy){
        if(StringUtils.isBlank(keyword) && categoryId == null){
            return  ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        List<Integer> categoryIdList = new ArrayList<Integer>();
        if(categoryId != null){
            Category category = categoryMapper.selectByPrimaryKey(categoryId);
            if(category == null && StringUtils.isBlank(keyword)){
                // 没有该分类,并且还没有关键字,这个时候返回一个空的结果集,不报错
                PageHelper.startPage(pageNum, pageSize);
                List<ProductListVo> productListVoList = Lists.newArrayList();
                PageInfo pageInfo = new PageInfo(productListVoList);
                return ServerResponse.createBySuccess(pageInfo);
            }
            categoryIdList = iCategoryService.selectCategoryAndChildrenById(category.getId()).getData();
        }
        if(StringUtils.isNotBlank(keyword)){
            keyword = new StringBuilder().append("%").append(keyword).append("%").toString();
        }
        PageHelper.startPage(pageNum, pageSize);
        // 排序处理
        if(StringUtils.isNotBlank(orderBy)){
            if(Const.ProductListOrderBy.PRICE_ASC_DESC.contains(orderBy)){
                //PageHelper.orderBy方法的参数是(peice desc)中间含有空格,需要分割再拼接
                String[] orderByArray = orderBy.split("_");
                PageHelper.orderBy(orderByArray[0]+" "+orderByArray[1]);
            }
        }
        List<Product> productList = productMapper.selectByNameAndCategoryIds(StringUtils.isBlank(keyword)?null:keyword,categoryIdList.size()==0?null:categoryIdList);
        List<ProductListVo> productListVoList = Lists.newArrayList();
        for(Product product : productList){
            ProductListVo productListVo = assembleProductListVo(product);
            productListVoList.add(productListVo);
        }
        PageInfo pageInfo = new PageInfo(productList);
        pageInfo.setList(productListVoList);
        return ServerResponse.createBySuccess(pageInfo);
    }

前端分页组件开发

html预留分页容器

<!--分页容器-->
      <div class="pagination">
</div>

在list/index.js列表中,加载分页

\'use strict\';
require(\'./index.css\');
require(\'page/common/nav/index.js\');
require(\'page/common/header/index.js\');
var _mm           = require(\'util/mm.js\');
var _product      = require(\'service/product-service.js\');
var Pagination      = require(\'util/pagination/index.js\');
var templateIndex = require(\'./index.string\');

var page = {
  data : {
    listParam : {
      keyword     : _mm.getUrlParam(\'keyword\')    || \'\',
      categoryId  : _mm.getUrlParam(\'categoryId\') || \'\',
      orderBy     : _mm.getUrlParam(\'orderBy\')    || \'default\',
      pageNum     : _mm.getUrlParam(\'pageNum\')    || 1,
      pageSize    : _mm.getUrlParam(\'pageSize\')   || 10
    }
  },
  init : function(){
    this.onLoad();
    this.bindEvent()
  },
  onLoad :function(){
    this.loadList();
  },
  bindEvent : function(){
    var _this = this;
    // 排序的点击事件
    $(\'.sort-item\').click(function(){
      var $this = $(this);
      // 页码置为1
      _this.data.listParam.pageNum= 1;
      // 如果点击的是默认排序
      if($this.data(\'type\') === \'default\'){
        // 已经是active样式
        if($this.hasClass(\'active\')){
          return;
        }
        // 其他
        else{
          $this.addClass(\'active\').siblings(\'.sort-item\')
            .removeClass(\'active asc desc\');
            _this.data.listParam.orderBy = \'default\';
        }
      }
      //点击价格排序
      else if($this.data(\'type\') === \'price\'){
        // active类的处理
        $this.addClass(\'active\').siblings(\'.sort-item\')
        .removeClass(\'active asc desc\');
        // 升序的处理
        if(!$this.hasClass(\'asc\')){
          $this.addClass(\'asc\').removeClass(\'desc\');
          _this.data.listParam.orderBy = \'price_asc\';
        }
        // 降序的处理
        else{
          $this.addClass(\'desc\').removeClass(\'asc\');
          _this.data.listParam.orderBy = \'price_desc\';
        }
      }
      // 重新加载列表
      _this.loadList();
    });
  },

  // 加载list数据
  loadList : function(){
    var _this   = this,
      listHtml  = \'\',
      listParam = this.data.listParam,
      $pListCon = $(\'.p-list-con\');
      //每次加载之前,显示loading
      $pListCon.html(\'<div class="loading"></div>\');
      // 删除参数中不必要的字段
    listParam.categoryId
    ? (delete listParam.keyword) : (delete listParam.categoryId);
    // 请求接口
    _product.getProductList(listParam, function(res){
      listHtml = _mm.renderHtml(templateIndex, {
        list : res.list
      });

      $pListCon.html(listHtml);
      _this.loadPagination({
        hasPreviousPage : res.hasPreviousPage,
        prePage         : res.prePage,
        hasNextPage     : res.hasNextPage,
        nextPage        : res.nextPage,
        pageNum         : res.pageNum,
        pages           : res.pages,
      });
    }, function(errMsg){
      _mm.errorTips(errMsg);
    });
  },

  //加载分页信息
  loadPagination : function(pageInfo){
    var _this = this;
    this.pagination ? \'\' : (this.pagination = new Pagination());
    this.pagination.render($.extend({}, pageInfo, {
      container : $(\'.pagination\'),
      onSelectPage : function(pageNum){
        _this.data.listParam.pageNum = pageNum;
        _this.loadList();
      }
    }));
  }

};
$(function(){
  page.init();
})

封装分页组件

pagination
  ├─index.css
  ├─index.js
  ├─index.string
  • index.js
\'use strict\';
require(\'./index.css\');
var _mm = require(\'util/mm.js\');
var templatePagination = require(\'./index.string\');

var Pagination = function(){
  var _this = this;
  this.defaultOption = {
    container    : null,
    pageNum      : 1,
    pageRange    : 3,
    onSelectPage :null
  };
  // 事件的处理
  $(document).on(\'click\', \'.pg-item\', function(){
    var $this = $(this);
    // 对于active和disabled按钮点击,不做处理
    if($this.hasClass(\'active\') || $this.hasClass(\'disabled\')){
        return;
    }
    typeof _this.option.onSelectPage === \'function\'
        ? _this.option.onSelectPage($this.data(\'value\')) : null;
});

};

// 渲染分页组件
Pagination.prototype.render = function(userOption){
  // 合并选项
  this.option = $.extend({},this.defaultOption,userOption);
  // 判断容器是否为合法的jQuery对象
  if(!(this.option.container instanceof jQuery)){
    return;
  }
  // 判断分页是否只有一页
  if(this.option.pages <= 1){
    return;
  }
  // 渲染分页内容
  this.option.container.html(this.getPaginationHtml());
};

// 获取分页的html, |上一页| 1 2 3 4 =5= 6 |下一页| 5/6
Pagination.prototype.getPaginationHtml = function(){
  var html      = \'\',
      option    = this.option,
      pageArray = [],
      start     = option.pageNum - option.pageRange > 0
        ? option.pageNum - option.pageRange : 1,
      end       = option.pageNum + option.pageRange < option.pages
        ? option.pageNum + option.pageRange : option.pages;
  // 上一页按钮的数据
  pageArray.push({
    name     : \'上一页\',
    value    : this.option.prePage,
    disabled : !this.option.hasPreviousPage
  });
  // 数字按钮的处理
  for(var i = start; i<= end; i++){
    pageArray.push({
      name     : i,
      value    : i,
      active : (i === option.pageNum)
    })
  };

  // 下一页按钮的数据
  pageArray.push({
    name     : \'下一页\',
    value    : this.option.nextPage,
    disabled : !this.option.hasNextPage
  });
  html = _mm.renderHtml(templatePagination, {
    pageArray : pageArray,
    pageNum   : option.pageNum,
    pages     : option.pages
  });
  return html;

};

module.exports = Pagination;
  • index.css

    .pg-content{
      text-align: center;
      color: #333;
    }
    .pg-content .pg-item{
      display: inline-block;
      height: 36px;
      line-height: 36px;
      padding: 0 15px;
      margin: 0 2px;
      border: 1px solid #ccc;
      background: #eee;
      cursor: pointer;
      -moz-user-select: none;
      -webkit-user-select: none;
      -ms-user-select: none;
      user-select: none;
    }
    .pg-content .pg-item.disabled{
      color: #ccc;
      background: none;
      cursor: auto;
    }
    .pg-content .pg-item.active{
      border: 1px solid #f6f6f6;
      background: none;
      cursor: auto;
    }
    .pg-content.pg-total{
      margin-left: 10px;
      background: none;
      cursor: auto;
    }
    
  • index.string

    <div class="pg-content">
      {{#pageArray}}
      {{#disabled}}
        <span class="pg-item disabled" data-value="{{value}}">{{name}}</span>
      {{/disabled}}
    
      {{^disabled}}
        {{#active}}
          <span class="pg-item active" data-value="{{value}}">{{name}}</span>
        {{/active}}
    
        {{^active}}
          <span class="pg-item" data-value="{{value}}">{{name}}</span>
        {{/active}}
    
      {{/disabled}}
      {{/pageArray}}
      <span class="pg-total">{{pageNum}} / {{pages}}</span>
    </div>
    

分类:

技术点:

相关文章:

  • 2022-01-08
  • 2022-01-08
  • 2021-08-27
  • 2022-01-08
  • 2022-01-03
  • 2021-06-18
  • 2021-07-31
  • 2021-06-29
猜你喜欢
  • 2022-01-08
  • 2021-11-29
  • 2022-01-08
  • 2022-01-08
  • 2022-01-08
  • 2021-09-16
  • 2019-08-21
相关资源
相似解决方案