和我一起写 Sencha Touch 超级强大分页组件

PageListView.js

Ext.define('ux.PageListView',{
	extend : 'Ext.Container',
	xtype : 'upagelistview',
	requires : [],
	config : {
		/**
		 * 数据存储对象
		 * @type 
		 */
		store : null,
		/**
		 * 数据显示格式
		 * @type 
		 */
		itemTpl : null,
		/**
		 * 排序按钮上的文字和list占位变量名对应的hashMap对象
		 * @type 
		 */
		namesMap : null,
		/**
		 * 表示当前页的变量
		 * @type 
		 */
		currentPageIndex : null,
		/**
		 * 表示总页数的变量
		 * @type 
		 */
		totalPageNum : null,
		/**
		 * 每页显示的记录条数,默认是10
		 * @type Number
		 */
		itemNumPerPage : 10,
		/**
		 * items显示的布局方式
		 * @type String
		 */
		layout : 'fit',
		/**
		 * 是否隐藏排序按钮
		 * @type Number
		 */
		isHiddenSortBtn : true,
		/**
		 * 是否显示搜索按钮
		 * @type Number
		 */
		isHiddenSearchBtn : true,
		/**
		 * 是否禁用跳页按钮
		 * @type Boolean
		 */
		isDisableJumpBtn : true,
		/**
		 * 临时store用于显示每页的数据
		 * @type 
		 */
		newStore : null,
		items : [{
					xtype : 'toolbar',
					docked : 'top',
					style : 'border:0;background-image:none;background-color:transparent;',
					layout : 'hbox',
					hidden : true,
					items : [{
						xtype : 'textfield',
						left : 0,
						hidden : true,//默认为隐藏
						listeners : {
							keyup: {//键盘弹起事件
						        fn: function() {
						        	var me = this.getParent().getParent();
						        	me.resetStore();
						        	me.search(this);
						        }
						    }
						}
					}, {
						xtype : 'toolbar',
						right : 0,
						style : 'border:0;background-image:none;background-color:transparent;',
						hidden : true,
						items : [ {
							xtype : 'textfield',
							width : '50%'
						}, {
							xtype : 'button',
							iconCls : 'check',
							iconWidth : '100%',
							width : '40%',
							handler : function(button) {
								button.disable();
								var me = button.getParent().getParent()
										.getParent();
								me.jump(me.items.items[0].items.items[1].items.items[0]);//调用当前的PageListView对象的对应方法
								button.enable();
							}
						}]
					}]
				},{
					xtype : 'toolbar',
					docked : 'top',
					style : 'border:0;background-image:none;background-color:transparent;',
					hidden : true,
					items : []
				},{
					xtype : 'list',
					listeners : {
						itemtap: {//点击
					        fn: function(list, index, target, record, e, eOpts) {
					        	var me = this.getParent();
					        	me.doTap(list, index, target, record, e, eOpts);
					        }
					    }
					}
				},
				{
					xtype : 'toolbar',
					docked : 'bottom',
					layout : 'hbox',
					style : 'border:0;background-image:none;background-color:transparent;',
					items : [
							{
								xtype : 'button',
								margin : '5 10 5 20',
								iconCls : 'arrow_left',
								handler : function(button) {
									button.disable();
									var me = button.getParent()
											.getParent();
									me.frontPage();//调用当前的PageListView对象的对应方法
									button.enable();
								}
							}, {
								margin : '5 10 5 10',
								xtype : 'button',
								text : '1/1',
								handler : function(button) {
									button.disable();
									var me = button.getParent().getParent();
									if(me.getIsDisableJumpBtn()) {//禁用跳转按钮
										button.enable();
										return;
									}
									var jumpToolbar = me.items.items[0].items.items[1];//获得跳转工具栏
									if(jumpToolbar.getHidden()) {
										if(me.items.items[0].getHidden()) {
											me.items.items[0].setHidden(false);
										}
										jumpToolbar.setHidden(false);
										if(me.items.items[0].items.items[0].getHidden()) {
											jumpToolbar.setWidth('100%');
										} else {
											jumpToolbar.setWidth('48%');
											me.items.items[0].items.items[0].setWidth('48%');
										}
									} else {
										jumpToolbar.setHidden(true);
										me.items.items[0].items.items[0].setWidth('100%');
										if(me.items.items[0].items.items[0].getHidden()) {
											me.items.items[0].setHidden(true);
										}
									}
									button.enable();
								}
							}, {
								xtype : 'button',
								margin : '5 20 5 10',
								iconCls : 'arrow_right',
								handler : function(button) {
									button.disable();
									var me = button.getParent()
											.getParent();
									me.nextPage();//调用当前的PageListView对象的对应方法
									button.enable();
								}
							}, {
								right : 80,
								margin : '5 10 5 20',
								xtype : 'button',
								iconCls : 'list',
								handler : function(button) {
									button.disable();
									var me = button.getParent()
											.getParent();
									me.showSortBar();
									button.enable();
								}
							}, {
								right : 0,
								margin : '5 20 5 10',
								xtype : 'button',
								iconCls : 'search',
								handler : function(button) {
									button.disable();
									var me = button.getParent().getParent();
									var searchTextfield = me.items.items[0].items.items[0];//获得搜索框
									if(searchTextfield.getHidden()) {
										if(me.items.items[0].getHidden()) {
											me.items.items[0].setHidden(false);
										}
										searchTextfield.setHidden(false);
										if(me.items.items[0].items.items[1].getHidden()) {
											searchTextfield.setWidth('100%');
										} else {
											searchTextfield.setWidth('48%');
											me.items.items[0].items.items[1].setWidth('48%');
										}
									} else {
										searchTextfield.setHidden(true);
										me.items.items[0].items.items[1].setWidth('100%');
										if(me.items.items[0].items.items[1].getHidden()) {
											me.items.items[0].setHidden(true);
										}
									}
									searchTextfield.setValue("");//防止隐藏后显示以前的数据还在文本里
									me.resetStore();//清空过滤和排序
									me.refreshPage();//刷新列表
									button.enable();
								}
							}]
				}]
	},
	
	/**
	 * 初始化方法
	 */
	initialize : function() {
		this.callParent();
		this.setConfigItemTpl();//将字段itemTpl传给list的itemTpl作为store的显示格式
		this.refreshPage();
		if(!this.getIsHiddenSortBtn()) {
			this.setFirstToolbar();//按按钮名字数组生成对应的按钮并将按钮添加到第一个工具栏里面
		}
		this.doHidden();
	},
	/**
	 * 设置上面工具栏显示或隐藏
	 */
	showSortBar : function() {
		if (this.items.items[1].getHidden()) {
			this.items.items[1].show();
		} else {
			this.items.items[1].hide();
		}
	},
	/**
	 * 将PageListView的itemTpl的值设置为PageListView中的List的itemTpl
	 */
	setConfigItemTpl : function() {
		this.items.items[2].setItemTpl(this.getItemTpl());
	},
	/**
	 * 设置上面那个toolbar按钮
	 */
	setFirstToolbar : function() {
		var arr = this.getNamesMap().getKeys();//获得map对象的所有键
		for(var i=0;i<arr.length;i++) {
			var btnName = arr[i];
			var btn = Ext.create('Ext.Button', {
					text : btnName,
					iconAlign : 'right',
					iconCls : 'default',
					margin : '5 10 5 20',
					handler : function(button) {
						var me = button.getParent().getParent();
						button.disable();//防止一直点一直响应
						var newStore = me.getNewStore();//复制一个当前PageListView类的对象的store用来操作
						var nm = button.getText();//当前按钮的名字
						if (button.getIconCls() == 'default'/*自定义支持*/ || button.getIconCls() == 'desc') {
							button.setIconCls('asc');//自定义支持
							newStore.sort(me.getNamesMap().get(nm),'ASC');
						} else {
							button.setIconCls('desc');//自定义支持
							newStore.sort(me.getNamesMap().get(nm),'DESC');
						}
						button.enable();
					}
				}
			);
			this.items.items[1].add(btn);
		}
	},
	/**
	 * 刷新方法
	 * 设置当前页为1,更新总页数,当前页和list的数据显示的newStore
	 */
	refreshPage : function() {//设置总页数和当前页
		var store = this.getStore();
		var count = store.getCount();
		var perCount = this.getItemNumPerPage();
		if(perCount == 0) {//防止后面除以0发生错误
			this.setTotalPageNum(1);
		}else {
			if(count % perCount == 0) {
				this.setTotalPageNum(count / perCount);//总记录数对每页取余为0表示刚好凑足整夜
			} else {
				rslt = Math.floor(count / perCount); //返回值为小于等于其数值参数的最大整数值。
				this.setTotalPageNum(rslt + 1);//总记录数对每页取余为0表示还多出不足一页的数据,应该再多加一页
			}
		}
		this.setCurrentPageIndex(1);//初始化设置当前页为1
		if(newStore == null) {//防止后面调用该方法重复创建该对象
			var newStore = Ext.create('Ext.data.Store');//新创建一个store
		} else {//如果不为空则清空原有数据
			newStore.removeAll();
		}
		newStore.setModel(store.getModel());//设置新建store的model
		newStore.setData(store.getRange(0,perCount-1));//设置新建store的数据为设置第一页的范围数据
		this.setNewStore(newStore);
		this.items.items[2].setStore(this.getNewStore());//将临时store放到list里面显示
		this.setCurrentAndTotalPage(1,this.getTotalPageNum());
	},
	/**
	 * 往前翻页
	 */
	frontPage : function() {
		this.resetSort()//清除排序
		var currentPageIndex = this.getCurrentPageIndex();//当前页
		if(currentPageIndex == 1) {//当前为第一页
			return;
		}
		this.setCurrentPageIndex(this.getCurrentPageIndex()-1);//当前页减1
		this.changePage(this.getCurrentPageIndex());//调用changePage
	},
	/**
	 * 页面跳转方法
	 */
	jump : function(textfield) {
		var text = textfield.getValue();//获得用户输入的页码
		var re = /^[1-9]+[0-9]*]*$/;  //判断里面有没有中括号的正则表达式
	    if (!re.test(text)) {//判断是否为正整数
	        alert("请输入正整数");  
	        textfield.focus();//设置焦点到输入框
	        return;  
	     } else {
	    	var index = parseInt(text);//将文本里面的字符串转换成数字
	    	this.setCurrentPageIndex(index);//当前页加1
	    	this.changePage(index);//按输入页面调用changePage方法
	     }
	},
	/**
	 * 往后翻页
	 */
	nextPage : function() {//bug:设置页码后向前翻页和向后翻页没用
		this.resetSort()//清除排序
		var total = this.getTotalPageNum();//总页数
		var currentPageIndex = this.getCurrentPageIndex();//当前页
		if(currentPageIndex == total) {//当前为最后一页
			return;
		}
		this.setCurrentPageIndex(this.getCurrentPageIndex()+1);//当前页加1
		this.changePage(this.getCurrentPageIndex());//调用changePage
	},
	/**
	 * 搜索方法
	 * 语法:[{列名}{规则}][{列名}{规则}]...
	 * 输入如:[{第1列}{.com}]
	 */
	search : function(textfield) {
		var store = this.getStore();//获得当前对象的store
		this.resetSort()//清除排序
		var text = textfield.getValue();//获得用户输入的搜索内容
		if(text.length == 0) {//防止内容删除到最后为空页面不显示
			this.resetStore();
			this.refreshPage();
			return;
		}
		var reg = /\[(.*?)\]/gi;
        var tmp = text.match(reg);
        if (tmp) {//搜索框中有表达式
            for (var i = 0; i < tmp.length; i++) {
            	var fullName = tmp[i].replace(reg, "$1");
            	var ruleReg = /\{(.*?)\}/gi;
            	var tmp2 = fullName.match(ruleReg);
                if (tmp2) {
                	var btnName = tmp2[0].replace(ruleReg, "$1");//获得对应的列名
                	var varName = this.getNamesMap().get(btnName);//获得对应的占位符变量名
                	var rule = tmp2[1].replace(ruleReg, "$1");//获得规则
                	var re = new RegExp(rule);
                	store.filter(varName,re);
                	this.refreshPage();
                }
            }
        } else {//非表达式形式过滤
            var me = this;
            store.filter([
			    Ext.create('Ext.util.Filter', {filterFn: function(item) {
			    	var keys = me.getNamesMap().getKeys();//获得map对象的所有键
			    	var len = keys.length;
			    	for(var i=0;i<len;i++) {//按hashMap的key循环
			    		value = me.getNamesMap().get(keys[i]);//获得hashMap里面key为当前key值的value
			    		return item.get(value).indexOf(text) != -1; //如果这个score里面的数据里面包含给定内容则返回
			    	}
			    }, root: 'data'})
			]);
			this.refreshPage();
        }
	},
	/**
	 * 设置当前页数和总页数的显示
	 */
	setCurrentAndTotalPage : function(current,total) {
		var btn = this.items.items[3].items.items[1];
		if(total==0) {//如果没有数据,不能显示为0页,则强行设置为总页数为1
			total = 1;
		}
		btn.setText(current + "/" + total);
	},
	/**
	 * 改变页码和list里面的store
	 * @returns
	 */
	changePage : function(currentPageIdx) {
		var store = this.getStore();
		this.resetSort()//清除排序
		var total = this.getTotalPageNum();//总页数
		if(currentPageIdx < 1 || currentPageIdx > total) {
			alert("不能跳到指定的页码");
			return;
		}
		var currentPageIndex = currentPageIdx;//当前页
		var perCount = this.getItemNumPerPage();//获得每一页多杀条记录
		var newStore = this.getNewStore();//获取newStore对象
		newStore.removeAll();//将newStore里面原有内容清空
		newStore.setModel(store.getModel());//设置新建store的model
		var beginIndex = (currentPageIndex-1)*this.getItemNumPerPage();//当前也的起始位置
		var endIndex = (currentPageIndex-1)*this.getItemNumPerPage()+(this.getItemNumPerPage()-1);//起始下标加每一页的显示个数
		var count = store.getCount();//总共记录数
		if(endIndex > count) {
			newStore.setData(store.getRange(beginIndex,count));//设置新建store的数据为设置当前页的范围数据
		} else {
			newStore.setData(store.getRange(beginIndex,endIndex));//设置新建store的数据为设置当前页的范围数据
		}
		this.setCurrentAndTotalPage(currentPageIndex,total);//设置当前页和总页数的显示
	},
	/**
	 * 重置store的排序和过滤
	 */
	resetStore : function() {
		var store = this.getStore();
		store.setSorters(null);//清除排序
		store.clearFilter();//清除过滤
	},
	/**
	 * 清空Store排序
	 */
	resetSort : function() {
		var store = this.getStore();
		store.setSorters(null);//清除排序
		var len = this.items.items[1].getItems().length;
		for(var i=0;i<len;i++) {
			this.items.items[1].getItems().items[i].setIconCls('default');
		}
	},
	doHidden : function() {
		this.items.items[3].items.items[3].setHidden(this.getIsHiddenSortBtn());
		this.items.items[3].items.items[4].setHidden(this.getIsHiddenSearchBtn());
	}
});

测试Model:

PageListModel.js

Ext.define('Notes.model.PageListModel', {
    extend : 'Ext.data.Model',
    xtype : 'pagelistmodel',
    config: {
        fields: ['title', 'content', 'date']
    }
});

测试Store:

PageListStore.js

Ext.define('Notes.store.PageListStore', {
   extend : 'Ext.data.Store',
   xtype : 'pageliststore',
   config : {
	   model : 'Notes.model.PageListModel',
	   sorters: 'date',
	   grouper: {
	       groupFn: function(record) {
	           return record.get('date');
	       }
	   },
	   data: [
	       { title : 'a标题1.com',   content : '内容1',  date : '1'},
	       { title : 'b标题2.com',   content : '内容2',  date : '1'},
	       { title : 'c标题3',   content : '内容3',  date : '1'},
	       { title : 'd标题4',   content : '内容4',  date : '1'},
	       { title : 'e标题5',   content : '内容5',  date : '1'},
	       { title : 'f标题6',   content : '内容6',  date : '1'},
	       { title : 'g标题7.com',   content : '内容7',  date : '1'},
	       { title : 'h标题8',   content : '内容8',  date : '1'},
	       { title : 'a标题1',   content : '内容1',  date : '1'},
	       { title : 'b标题2',   content : '内容2',  date : '1'},
	       { title : 'c标题3',   content : '内容3',  date : '1'},
	       { title : 'd标题4',   content : '内容4',  date : '1'},
	       { title : 'e标题5',   content : '内容5',  date : '1'},
	       { title : 'f标题6',   content : '内容6',  date : '1'},
	       { title : 'g标题7',   content : '内容7',  date : '1'},
	       { title : 'h标题8',   content : '内容8',  date : '1'}
	   ]
   }
});

直接生成该类实例页面测试:

var map = Ext.create('Ext.util.HashMap');
		map.add( "第1列", "title" );
		map.add( "第2列", "content" );
		map.add( "第3列", "date" );
		var store = Ext.create('Notes.store.PageListStore');
		var pageListView = Ext.create('Notes.view.pagelist.PageListView',{
			store : store,
			itemTpl : '<table id="table1" style="width:100%;font-size:15px;"><tr><td style="width:30%;">{title}</td><td style="width:30%;">【{content}】</td><td style="width:30%;">【{date}】</td></tr></table>',
			namesMap : map,
			itemNumPerPage : 10,
			isHiddenSortBtn : false,
			isHiddenSearchBtn : false,
			isDisableJumpBtn : false
		});
		Ext.Viewport.add(pageListView);

当然你也可以用一个页面来继承自该组件并重写里面的属性和方法来自定义分页页面,例如:

Ext.define('Notes.view.treelist.MyPageListView', {
	extend : 'ux.upagelistview',
	xtype : 'mypagelistview',
	config : {
	},
	//其他代码
}
//效果和下面这样写是一样的,因为不写会使用父类的默认属性,默认就是这些功能都不配置
Ext.define('Notes.view.treelist.MyPageListView', {
	extend : 'ux.upagelistview',
	xtype : 'mypagelistview',
	config : {
		/**
		 * 数据存储对象
		 * @type 
		 */
		store : null,
		/**
		 * 数据显示格式
		 * @type 
		 */
		itemTpl : null,
		/**
		 * 排序按钮上的文字和list占位变量名对应的hashMap对象
		 * @type 
		 */
		namesMap : null,
		/**
		 * 表示当前页的变量
		 * @type 
		 */
		currentPageIndex : null,
		/**
		 * 表示总页数的变量
		 * @type 
		 */
		totalPageNum : null,
		/**
		 * 每页显示的记录条数,默认是10
		 * @type Number
		 */
		itemNumPerPage : 10,
		/**
		 * items显示的布局方式
		 * @type String
		 */
		layout : 'fit',
		/**
		 * 是否隐藏排序按钮
		 * @type Number
		 */
		isHiddenSortBtn : true,
		/**
		 * 是否显示搜索按钮
		 * @type Number
		 */
		isHiddenSearchBtn : true,
		/**
		 * 是否禁用跳页按钮
		 * @type Boolean
		 */
		isDisableJumpBtn : true,
		//其它代码...
	}
});

你可以适当的调一下样式使它看上去更好看。

下面附上效果图:

1.配置上了所有的东西

181941_b80j_259577.jpg

2.取消配置了所有的按钮

181942_HBeT_259577.jpg

3.整个搜索可以说是这个组件的亮点之一,你可以全文搜索,也可以按列搜索。不过按列搜索的语法过于复杂,你可以将源码进行适当的优化,使其使用更为方便,好了,介绍结束,好好看下源码来完成你自己的分页组件吧!



转载于:https://my.oschina.net/u/259577/blog/207271

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值