当前位置: 首页 > 科技观察

miniuidatagrid的客户端分页方案

时间:2023-03-16 02:12:51 科技观察

官方方案官方在“在线示例”中给出了一个简单的客户端分页方案,代码就不贴了,这里是基本思路和处理过程。首先绑定一个preload事件,在该事件中设置event.cancel=true,防止datagrid在翻页时请求服务器加载数据。那么数据从何而来?当然,只能通过在外部写一个ajax进程来获取。但是获取到的数据并没有直接交给datagrid,而是缓存起来放在dataResult中。现在继续讲preload。除了防止datagrid向服务器请求数据,preload还需要从缓存中找到页码对应的数据行,通过setData设置渲染到datagrid。OK,这件事由自定义函数fillData来实现。当然这里也要做页面相关的事情,分别是setTotalCount()、setPageIndex()和setPageCount()。官方方案展示了miniuidatagrid客户端分页方案的基本思路,但是这个例子太简单了。想把之前的服务端分页改成客户端分页怎么办?已经有对load()、setData()等的调用。现在如何以最少的代码更改实现客户端分页?上面的类ClientPagination首先想到的是保留原来的load()和setData()接口,但是改变它们的行为。load()的原始行为是提交[XXX参数],从服务器加载指定页面的数据;现在它需要加载所有数据。setData()本来就是把所有需要显示的数据行设置到datagrid中,不考虑分页(比如一次可以显示200条数据);但是现在如果数据集的量太大,需要通过客户端页面一页一页的展示出来。JavaScript语言是动态的,这使得替换方法成为可能,这是很多静态语言做不到的事情。替换法也是解决这个问题最简单的方法。当然,除此之外,我们还要感谢miniui没有使用jQuery扩展(如$grid.datagrid("setData",...))来实现组件。替换方法成为可能,但是原来的方法还是要保留,因为我们需要通过原来的方法来操作datagrid。所以ClientPagination类应该是这样的:ClientPagination的基本结构注意:本文所有代码都是ES6语法constMETHODS=["setData","load"];classClientPagination{constructor(datagrid){this._datagrid=datagrid;this._origin={};this.setup();}setup(){//TODO暂存this._datagrid的load、setData等方法//并为this._datagrid设置新的方法和注册事件}destroy(){//TODO恢复this._datagrid的方法,注销事件}onBeforeLoad(){//按照官方的解决方案e.cancel=true;letpageIndex=e.data.pageIndex;letpageSize=e.data.pageSize;this。setPageData(pageIndex,pageSize);}//参考datagrid.load的函数签名load(params,success,fail){//TODO实现加载数据保存到this._data//然后调用this.setData()保存和显示数据}setData(data){//TODO保存数据到this._data,//然后调用this.setPageData()显示当前页面的数据}setPageData(pageIndex,pageSize){//TODO从缓存的this._datapageIndex和pageSize中取出要显示的数据行//然后通过this._origin.setData()设置到datagrid中}}设置和释放客户端分页分别是setup和destroy绑定和取消绑定数据网格setup(){constgrid=this._datagrid;的客户端分页进程constoriginal=this._origin={};METHODS.forEach(name=>{//临时原方法origin[name]=grid[name].bind(grid);//替换为该类中定义的新方法grid[name]=this[name].bind(this);});//暂时存储事件处理程序,以备后用this._onBeforeLoad=this.onBeforeLoad.bind(this);grid.on("beforeload",this._onBeforeLoad);}destroy(){this._origin={};this._datagrid.un("beforeload",this._onBeforeLoad);this._datagrid=null;}从官方示例中的关键代码onBeforeLoad和setPageData是参考官方解决方案中的beforeload事件和fillData方法编写的上面已经有onBeforeLoad的代码,现在是setPageData的代码setPageData(pageIndex,pageSize){constallData=this._data;letstart=pageIndex*pageSize;if(start>=allData.length){start=0;pageIndex=0;}constend=Math.min(start+pageSize,allData.length);constpageData=[];for(leti=start;i{this.setData(data);if(typeofsuccess==="function"){success(data);}},()=>{if(typeofsuccess==="function"){fail();}});}重写setData,setData也被替换,参数是整个表格的数据,但是只能显示当前页的数据setData(data){constrows=Array.isArray(data)?data:(data.data||[]);this._data=rows;this.setPageData(this。或其他合适的初始化位置)加上ClientPagination.wrap(mini.get("datagridId"));如果你需要销毁,你可以这样做varcpBlabla=ClientPagination.wrap(mini.get("datagridId"));....cpBalbal.destory();总结通过ClientPagination的封装,可以在不改变原有业务代码和设置的情况下实现miniuidatagrid的客户端分页,但是这种实现只是解决了目前的问题。如果有新的需求:当页码在前三页时使用客户端分页减少数据加载量,翻到后面时使用服务端分页