JQuery 构建客户/服务分离的链接模型中Table分页代码效率初探


Posted in Javascript onJanuary 22, 2010

如果你所在公司的开发环境或者项目的开发环境处于单一语言的开发环境之中,框架不适用,因为框架的使用范围之一就是针对一个项目中存在多个语言开发的业务模块,而新项目都需要这些模块的功能,按照以前的习惯,肯定是重新开发,至少也是将其他的语言开发的业务功能变成webservice接口供新代码调用,在这种情况下,本文讨论的框架就可以派上用场并且还能在客户端消除语言差异,只使用纯javascript和html静态代码进行开发。

当然即使在单一的语言环境下,仍然可以使用该模型进行开发,不过开发人员就无法享受到各种优秀的服务端控件(Asp.net控件,专门为java开发的控件等等),只能使用纯javascript控件,这会对开发人员造成不方便(特别是依赖服务端控件的开发人员尤其如此)。

经过以上两篇博文的谈论,我们发现这种模型是完全有用武之地的,它将服务端的语言彻底和客户端分离,开发客户端的人员(在理论条件下)可以完全忽略服务端的语言种类,只进行纯Javascript开发,利用JQUERY中提供的AJAX方法同服务端方法通信。

JQuery 构建客户/服务分离的链接模型中Table分页代码效率初探

 

从上面的整体架构图,我们看出:其客户端都是WebService接口来获取数据和传送数据的,而服务端业务模型是什么语言开发的,完全不需要关注(当然在现实情况下,一般WebService接口最好同服务端业务模型是一个语言开发的)。

 

这个时候可以会首先想到效率的问题:

众所周知,WebService接口的效率较慢,那么这样搞是不是会让采用这种结构模型开发的网站速度变慢,与其这样,还不如采用常规的方法开发,不仅熟悉而且速度也不错呢?

 

先看下面几个推论:

1)WebService接口的效率慢 <---> 异步获取数据 ,两者互相能够抵消吗?

2)客户端采用Post的方式,可以减少数据的量,能部分抵消WebService接口的效率慢吗?

以上两个推论,虽然我们没完全做过对比,但可以肯定的说,它们是有对冲效率的,WebService慢,反映在页面端无怪乎就是页面等待长时间不出来,造成用户体验下降,但因为采用异步获取的方式,这种情况还会出现吗?应该不会。

在传送过程中,采用Post方式,数据量大大减少,又采用了异步方式,实际运行效果应该是相当不错的。

 

但对于某些特殊情况并且有很普遍的问题,比如Table表格的分页情况,我们又该怎么处理呢?

Table表格数据填充和分页 这个在页面上非常普遍的问题确对以上的推论造成了威胁,究其原因就是因为一般的分页代码都是把数据返回到客户端内存中,然后进行分页,因此大量的数据从服务端传递到客户端,必然造成问题,其实这个问题不仅仅是这个框架的问题,所有采用这种方式进行分页的代码都存在这样的问题,只不过这个框架采用WebService接口与客户端通信,才导致这个问题的重要性被无限放大了。

以下我们就来讨论在这种框架下进行分页的处理:

环境:Visual studio 2005

         JQuery 1.3.2

         SQLServer2005

分页原理:

         JQuery 构建客户/服务分离的链接模型中Table分页代码效率初探

 

从上图中,看到不管数据表中有多少数据,每次返回到客户端的数据都是一页的数据,这种方法没有采用存储过程方式,而是在webservice端进行处理的。

 

代码片段:

服务端填充Table表格代码----:

说明:

TB_WEB_NZ_INVESTMENT  是实体类,对应表对象

FlowID  表对象的字段属性,通过它获取一类相似的数据记录

 

代码中有对【首页】,【尾页】,【中间页】的元素进行过滤,对返回的泛型List对象进行范围过滤

/// <summary> 
/// 分页功能的表格填充服务端 
/// </summary> 
/// <param name="FlowID"></param> 
/// <param name="PageCount">每页数目</param> 
/// <param name="CurrentPage">当前页</param> 
/// <returns></returns> 
[WebMethod] 
[ScriptMethod(ResponseFormat = ResponseFormat.Json)] 
public string Load_ContributivePerson_Table(string FlowID, int PageCount, int CurrentPage) 
{ 
List<TB_WEB_NZ_INVESTMENT> list = new List<TB_WEB_NZ_INVESTMENT>(); list = objBusinessFacade.GetTB_WEB_NZ_INVESTMENT_CollectionByFlowID(FlowID); 
int TotalPageCount = 0; 
if (PageCount != 0) 
{ 
if ((list.Count % PageCount) > 0) 
{ 
TotalPageCount = list.Count / PageCount + 1; 
} 
else 
{ 
TotalPageCount = list.Count / PageCount; 
} 
}//if 
if (CurrentPage == 1) 
{ 
//第一页 
if (PageCount < list.Count) 
{ 
list.RemoveRange(PageCount, list.Count - PageCount); 
} 
} 
else if (CurrentPage > 1 && CurrentPage < TotalPageCount) 
{ 
//中间页 
int R1 = (CurrentPage - 1) * PageCount-1; 
int R2 = CurrentPage * PageCount; 
List<TB_WEB_NZ_INVESTMENT> list1 = new List<TB_WEB_NZ_INVESTMENT>(); 
for (int i = 0; i < list.Count; i++) 
{ 
if (i > R1&&i<R2) 
{ 
list1.Add(list[i]); 
} 
} 
list.Clear(); 
list = list1; 
} 
else if (CurrentPage == TotalPageCount) 
{ 
//尾页 
//但返回的显示对象列表确只能是最后一页里面的记录 
//这里需要剔除不是最后一页的元素对象 
list.RemoveRange(0,(CurrentPage-1) * PageCount); 
} 
return new JavaScriptSerializer().Serialize(list); 
}

原理说明图:-----------------------

JQuery 构建客户/服务分离的链接模型中Table分页代码效率初探

结合以上代码和该图讲解:

1)首页操作

list.RemoveRange(PageCount, list.Count - PageCount); 

翻译成数字:list.RemoveRange(5,14-5); 

首页显示的元素:A1 A2 A3 A4 A5 对应的索引:0 1 2 3 4

list.RemoveRange(5,14-5);  //排除索引值为5(含自身)的后面的所有元素,这样列表中只有A1-A5 元素

 

2)中间页操作:(这里就是第2页)

JQuery 构建客户/服务分离的链接模型中Table分页代码效率初探

CurrentPage 等于 2

 int R1 = (CurrentPage - 1) * PageCount-1; 等于4
 int R2 = CurrentPage  * PageCount;             等于10

 

R1 和R2 代表两个区间范围索引,即在索引4(不含索引4) 到 索引10(不含索引10) 之间的元素,是我们要取出的元素

List<TB_WEB_NZ_INVESTMENT> list1 = new List<TB_WEB_NZ_INVESTMENT>(); 
for (int i = 0; i < list.Count; i++) 
{ 
if (i > R1&&i<R2) 
{ 
list1.Add(list[i]); 
} 
} 
list.Clear(); 
list = list1;

3)尾页操作:
//尾页
//但返回的显示对象列表确只能是最后一页里面的记录
//这里需要剔除不是最后一页的元素对象
list.RemoveRange(0,(CurrentPage-1) * PageCount);
尾页的代码就简单一些。
从以上的服务端代码,我们看出虽然每次从数据库返回全部的代码到webservice端,但通过这个方法,就将其无用的记录全部过滤了,把剩下的元素传递到客服端,这样不管记录有多少条,每次返回页面的都只有一点点,提高了效率,避免了webservice传递大数据的问题,这样这个框架在传递大数据的方面基本不存在任何问题(排除一些及其特殊的东西),运用这个框架在效率方面不存在任何问题,甚至比普通的页面还要快。
客户端代码片段:
客户端就不再详细说明了,客户端需要传入
PageCount

每页显示的记录数
CurrentPage 当前页数
表格的html:
代码

<table id="TData" width="100%" > 
<thead id="thead"> 
<tr id="TR_Header" class="MyTableTR_Header" align="center" style=" height:25px"> 
<td style="width:1%; display:none" class="MyTableTD"></td> 
<td style="width:10%" >投资人类型</td> 
<td style="width:10%">投资人</td> 
<td style="width:10%">出资方式</td> 
<td style="width:10%">认缴出资额</td> 
<td style="width:10%">实缴出资额</td> 
<td style="width:10%">出资比例</td> 
<td style="width:15%">余额缴付期限</td> 
<td style="width:15%">资料是否完整</td> 
<td style="width:10%">操作</td> 
</tr> 
</thead> 
<tbody id="tbody_Data"></tbody> 
<tfoot id="tfoot_foot"> 
<tr align="right"> 
<td style="width:100%" colspan="9"> 
<a href="#" id="First_A">首页</a> 
<a href="#" id="Prev_A">上一页</a> 
<a href="#" id="Next_A">下一页</a> 
<a href="#" id="Last_A">尾页</a> 
跳到<input id="ToPageNo" type="text" style="width:20px; height:10px; font-size:9px"/>页 | 
总页数:<span id="showTotalPage" style="color:Red"></span>页 
</td> 
</tr> 
</tfoot> 
</table>

填充数据的js函数:
代码
//引导数据填充表格(Table) 
function Load_TableData(FlowID,CurrentPage) 
{ 
$.ajax({ 
type: "POST", 
url: IPServer +"JsonService.asmx/Load_ContributivePerson_Table", 
data:"{FlowID:'"+FlowID+"',PageCount:"+PageCount+",CurrentPage:" + CurrentPage +"}" , 
contentType: "application/json; charset=utf-8", 
dataType: "json", 
success: function(msg){ 
msg = msg.replace(new RegExp('(^|[^\\\\])\\"\\\\/Date\\((-?[0-9]+)\\)\\\\/\\"', 'g'), "$1new Date($2)"); 
var data = eval("(" + msg + ")"); 
var strTR=""; 
var RowCount = 1; 
jQuery.each(data, function(rec) { 
strTR += "<TR id='TR_" + RowCount + "' class='MyTableTR' align='center' >"; 
strTR += " <TD style='width:1%; display:none' id='Key_"+RowCount+"' class='MyTableTD' >" + this.INVID + "</TD>"; 
strTR += " <TD style='width:10%' class='MyTableTD' >" + this.INVTYPEName + "</TD>"; 
strTR += " <TD style='width:10%' class='MyTableTD' >" + this.INV + "</TD>"; 
strTR += " <TD style='width:10%' class='MyTableTD' >" + this.CONFORM + "</TD>"; 
strTR += " <TD style='width:10%' class='MyTableTD' >" + this.SUBCONAM + "</TD>"; 
strTR += " <TD style='width:10%' class='MyTableTD' >" + this.ACCONAM + "</TD>"; 
strTR += " <TD style='width:10%' class='MyTableTD' >" + this.CONPROP + "</TD>"; 
strTR += " <TD style='width:15%' class='MyTableTD' >" + this.BALDEPER_ShortString + "</TD>"; 
strTR += " <TD style='width:15%' class='MyTableTD' >" + this.IsDataCompleteness + "</TD>"; 
strTR += " <TD style='width:10%' class='MyTableTD' ><a id='Link_"+RowCount+"' href='#' >选择</a></TD>"; 
strTR += "</TR>"; 
RowCount++; 
});//jQuery.each 
$("#tbody_Data").empty(); 
$("#tbody_Data").append(strTR); 
$("#CurrentPage").html(CurrentPage); 
}, 
error:function(msg){ 
alert( "Error: " + msg ); 
} 
}); 
}//function Load_TableData()

首页,上一页,下一页,尾页的操作:
说明:
$("#CurrentPage").html()

存储当前页
(调用代码在上个函数红色处) 
$("#TotalPageCount").html()

存储总页数
(调用代码有个专门的函数,见下面)

代码
$("#First_A").click(function(){//首页 链接操作 
Load_TableData(strFlowID,1); 
}); 
$("#Prev_A").click(function(){//上一页 链接操作 
var intCurrentPage = Number(c); 
if(intCurrentPage>1) 
{ 
Load_TableData(strFlowID,intCurrentPage-1); 
} 
}); 
$("#Next_A").click(function(){//下一页 链接操作 
var intCurrentPage = Number($("#CurrentPage").html()); 
var intTotalPageCount = Number($("#TotalPageCount").html()); 
if(intCurrentPage<intTotalPageCount) 
{ 
Load_TableData(strFlowID,intCurrentPage+1); 
} 
}); 
$("#Last_A").click(function(){//尾页 链接操作 
intLastPage = Number($("#TotalPageCount").html()); 
Load_TableData(strFlowID,intLastPage); 
});

返回总页数的客户端函数:
代码
//返回页数 
function Get_TableData_TotalCount(FlowID) 
{ 
$.ajax({ 
type: "POST", 
url: IPServer +"JsonService.asmx/Get_ContributivePersonTable_TotalPageCount", 
data:"{FlowID:'"+FlowID +"',PageCount:"+PageCount+"}" , 
contentType: "application/json; charset=utf-8", 
dataType: "json", 
success: function(msg){ 
var data = eval("(" + msg + ")"); 
jQuery.each(data, function(rec) { 
$("#TotalPageCount").html(this.Info); 
$("#showTotalPage").html(this.Info); 
});//jQuery.each 
}, 
error:function(msg){ 
alert( "Error: " + msg ); 
} 
}); 
} 
<div id="CurrentPage" ></div> 
<div id="TotalPageCount" ></div>

最后效果图:

JQuery 构建客户/服务分离的链接模型中Table分页代码效率初探 

总结:

Table数据填充并分页还有很多方法,这里只是提供了一种通过服务端就进行过滤的方法,让其返回客户端的数据始终就一点,提高了效率。

框架的应用探索正在稳步进行中。。。。。。

Javascript 相关文章推荐
编写Js代码要注意的几条规则
Sep 10 Javascript
jQuery 源码分析笔记(2) 变量列表
May 28 Javascript
IE6已终止操作问题的2种情况及解决
Apr 23 Javascript
详解JavaScript中|单竖杠运算符的使用方法
May 23 Javascript
BootStrapTable服务器分页实例解析
Dec 20 Javascript
JS基于正则表达式的替换操作(replace)用法示例
Apr 28 Javascript
js+html制作简单日历的方法
Jun 27 Javascript
浅谈关于axios和session的一些事
Jul 13 Javascript
JS基于设计模式中的单例模式(Singleton)实现封装对数据增删改查功能
Feb 06 Javascript
Jquery获取radio选中值实例总结
Jan 17 jQuery
layui点击左侧导航栏,实现不刷新整个页面,只刷新局部的方法
Sep 25 Javascript
解决vue 给window添加和移除resize事件遇到的坑
Jul 21 Javascript
被jQuery折腾得半死,揭秘为何jQuery为何在IE/Firefox下均无法使用
Jan 22 #Javascript
jQuery 入门级学习笔记及源码
Jan 22 #Javascript
JQuery 确定css方框模型(盒模型Box Model)
Jan 22 #Javascript
Jquery实战_读书笔记2 选择器
Jan 22 #Javascript
Jquery实战_读书笔记1—选择jQuery
Jan 22 #Javascript
jquery last-child 列表最后一项的样式
Jan 22 #Javascript
javascript 拖放效果实现代码
Jan 22 #Javascript
You might like
不用数据库的多用户文件自由上传投票系统(3)
2006/10/09 PHP
PHP求最大子序列和的算法实现
2011/06/24 PHP
php cookie中点号(句号)自动转为下划线问题
2014/10/21 PHP
CodeIgniter框架数据库基本操作示例
2018/05/24 PHP
php的无刷新操作实现方法分析
2020/02/28 PHP
Thinkphp 框架配置操作之动态配置、扩展配置及批量配置实例分析
2020/05/15 PHP
JavaScript不刷新实现浏览器的前进后退功能
2014/11/05 Javascript
谈谈jQuery之Deferred源码剖析
2016/12/19 Javascript
js中开关变量使用实例
2017/02/24 Javascript
ES6中Math对象新增的方法实例详解
2017/04/25 Javascript
js Dom实现换肤效果
2017/10/21 Javascript
electron实现qq快捷登录的方法示例
2018/10/22 Javascript
vue element 生成无线级左侧菜单的实现代码
2019/08/21 Javascript
JavaScript生成一个不重复的ID的方法示例
2019/09/16 Javascript
详解VUE中的插值( Interpolation)语法
2020/10/18 Javascript
vue3.0自定义指令(drectives)知识点总结
2020/12/27 Vue.js
使用Python开发windows GUI程序入门实例
2014/10/23 Python
python在linux系统下获取系统内存使用情况的方法
2015/05/11 Python
黑科技 Python脚本帮你找出微信上删除你好友的人
2016/01/07 Python
python 重定向获取真实url的方法
2018/05/11 Python
Python jieba库用法及实例解析
2019/11/04 Python
Python实现的北京积分落户数据分析示例
2020/03/27 Python
Python xlrd模块导入过程及常用操作
2020/06/10 Python
Goodee官方商店:迷你投影仪
2021/03/15 全球购物
JAVA的事件委托机制和垃圾回收机制
2014/09/07 面试题
C++的几个面试题附答案
2016/08/03 面试题
高中军训感言1000字
2014/03/01 职场文书
春风行动实施方案
2014/03/28 职场文书
入职担保书怎么写
2014/05/12 职场文书
2015年班主任个人工作总结
2015/03/31 职场文书
革命电影观后感
2015/06/18 职场文书
高中数学教学反思范文
2016/02/18 职场文书
python opencv人脸识别考勤系统的完整源码
2021/04/26 Python
使用python向MongoDB插入时间字段的操作
2021/05/18 Python
Jupyter notebook 更改文件打开的默认路径操作
2021/05/21 Python
Python接口自动化之文件上传/下载接口详解
2022/04/05 Python