手寫前端分頁組件
服務端接口開發
-
個人理解
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。動態分頁需要用到兩個參數pageNum
和pageSize
@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>