当然即使在单一的语言环境下,仍然可以使用该模型进行开发,不过开发人员就无法享受到各种优秀的服务端控件(Asp.net控件,专门为java开发的控件等等),只能使用纯javascript控件,这会对开发人员造成不方便(特别是依赖服务端控件的开发人员尤其如此)。
经过以上两篇博文的谈论,我们发现这种模型是完全有用武之地的,它将服务端的语言彻底和客户端分离,开发客户端的人员(在理论条件下)可以完全忽略服务端的语言种类,只进行纯Javascript开发,利用JQUERY中提供的AJAX方法同服务端方法通信。
从上面的整体架构图,我们看出:其客户端都是WebService接口来获取数据和传送数据的,而服务端业务模型是什么语言开发的,完全不需要关注(当然在现实情况下,一般WebService接口最好同服务端业务模型是一个语言开发的)。
这个时候可以会首先想到效率的问题:
众所周知,WebService接口的效率较慢,那么这样搞是不是会让采用这种结构模型开发的网站速度变慢,与其这样,还不如采用常规的方法开发,不仅熟悉而且速度也不错呢?
先看下面几个推论:
1)WebService接口的效率慢 <---> 异步获取数据 ,两者互相能够抵消吗?
2)客户端采用Post的方式,可以减少数据的量,能部分抵消WebService接口的效率慢吗?
以上两个推论,虽然我们没完全做过对比,但可以肯定的说,它们是有对冲效率的,WebService慢,反映在页面端无怪乎就是页面等待长时间不出来,造成用户体验下降,但因为采用异步获取的方式,这种情况还会出现吗?应该不会。
在传送过程中,采用Post方式,数据量大大减少,又采用了异步方式,实际运行效果应该是相当不错的。
但对于某些特殊情况并且有很普遍的问题,比如Table表格的分页情况,我们又该怎么处理呢?
Table表格数据填充和分页 这个在页面上非常普遍的问题确对以上的推论造成了威胁,究其原因就是因为一般的分页代码都是把数据返回到客户端内存中,然后进行分页,因此大量的数据从服务端传递到客户端,必然造成问题,其实这个问题不仅仅是这个框架的问题,所有采用这种方式进行分页的代码都存在这样的问题,只不过这个框架采用WebService接口与客户端通信,才导致这个问题的重要性被无限放大了。
以下我们就来讨论在这种框架下进行分页的处理:
环境:Visual studio 2005
JQuery 1.3.2
SQLServer2005
分页原理:
从上图中,看到不管数据表中有多少数据,每次返回到客户端的数据都是一页的数据,这种方法没有采用存储过程方式,而是在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);
}
原理说明图:-----------------------
结合以上代码和该图讲解:
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页)
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>
最后效果图:
总结:
Table数据填充并分页还有很多方法,这里只是提供了一种通过服务端就进行过滤的方法,让其返回客户端的数据始终就一点,提高了效率。
框架的应用探索正在稳步进行中。。。。。。
JQuery,客户,服务分离
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。