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 相关文章推荐
用javascript实现的图片马赛克后显示并切换加文字功能
Apr 21 Javascript
JS通过相同的name进行表格求和代码
Aug 18 Javascript
浏览器复制插件zeroclipboard使用指南
Mar 26 Javascript
Ionic如何创建APP项目
Jun 03 Javascript
JavaScript必知必会(九)function 说起 闭包问题
Jun 08 Javascript
Bootstrap基本组件学习笔记之input输入框组(9)
Dec 07 Javascript
使用JavaScript判断用户输入的是否为正整数(两种方法)
Feb 05 Javascript
javascript 判断当前浏览器版本并判断ie版本
Feb 17 Javascript
vue实现点击选中,其他的不选中方法
Sep 05 Javascript
vue改变循环遍历后的数据实例
Nov 07 Javascript
Vue js with语句原理及用法解析
Sep 03 Javascript
微信小程序实现滚动Tab选项卡
Nov 16 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
php cookie的操作实现代码(登录)
2010/12/29 PHP
关于PHP中Session文件过多的问题及session文件保存位置
2016/03/17 PHP
用js模拟JQuery的show与hide动画函数代码
2010/09/20 Javascript
jquery实现效果比较好的table选中行颜色
2014/03/25 Javascript
用原生js做个简单的滑动效果的回到顶部
2014/10/15 Javascript
探讨JavaScript中的Rest参数和参数默认值
2015/07/29 Javascript
详解为Angular.js内置$http服务添加拦截器的方法
2016/12/20 Javascript
jQuery UI 实例讲解 - 日期选择器(Datepicker)
2017/09/18 jQuery
微信小程序支付之c#后台实现方法
2017/10/19 Javascript
vue基于mint-ui的城市选择3级联动的示例
2017/10/25 Javascript
JavaScript函数式编程(Functional Programming)高阶函数(Higher order functions)用法分析
2019/05/22 Javascript
layer.open弹层查看缩略图的原图,自适应大小的实例
2019/09/05 Javascript
vue 路由懒加载中给 Webpack Chunks 命名的方法
2020/04/24 Javascript
html-webpack-plugin修改页面的title的方法
2020/06/18 Javascript
Python中使用wxPython开发的一个简易笔记本程序实例
2015/02/08 Python
Python判断值是否在list或set中的性能对比分析
2016/04/16 Python
Python基于二分查找实现求整数平方根的方法
2016/05/12 Python
pandas数据框,统计某列数据对应的个数方法
2018/04/11 Python
python复制列表时[:]和[::]之间有什么区别
2018/10/16 Python
Python3基础教程之递归函数简单示例
2019/06/07 Python
python目标检测给图画框,bbox画到图上并保存案例
2020/03/10 Python
Python生成器实现简单&quot;生产者消费者&quot;模型代码实例
2020/03/27 Python
Python类中的装饰器在当前类中的声明与调用详解
2020/04/15 Python
django下创建多个app并设置urls方法
2020/08/02 Python
python subprocess pipe 实时输出日志的操作
2020/12/05 Python
Python扫描端口的实现
2021/01/25 Python
英国男女奢华内衣和泳装购物网站:Figleaves
2017/01/28 全球购物
英国最大的独立摄影零售商:Park Cameras
2019/11/27 全球购物
编写一子程序,将一链表倒序,即使链表表尾变表头,表头变表尾
2016/02/10 面试题
小区门卫管理制度
2014/01/29 职场文书
大学毕业感言一句话
2014/02/06 职场文书
酒店管理毕业生自荐信
2014/05/25 职场文书
红歌会主持词
2015/07/02 职场文书
导游词之南京莫愁湖公园
2019/11/13 职场文书
Python 把两层列表展开平铺成一层(5种实现方式)
2021/04/07 Python
Prometheus 监控MySQL使用grafana展示
2021/08/30 MySQL