ajax library的客户端基本库里提供了异步访问服务端页面的脚本方法,很好的封装了xmlHttpRequest的常用方法,并与aspnet的方法实现了无缝的集成,很方便的在客户端异步的调用服务器的方法。利用这些脚本方法,仅仅从服务器端返回纯粹的数据,最终的如何显示这些数据由客户端完成。不像ajax.net里的那些服务器控件,比如updatepanel包装下的控件。虽然是无刷新了,但是最终控件的生成还是由服务器端完成,然后成堆的返回到客户端,服务器的负担还是没减少。
分页是我们常用的显示数据的操作,按照原来aspnet的服务器控件模式,datagrid包办了获取数据和分页的操作,而用客户端脚本,只需要服务器提供数据即可,下面用客户端脚本完成在客户端的分页功能。这种分页的基本步骤是,客户端首先从服务器那获取总记录数,然后计算分页信息,翻页的时候将页码和页面大小发送到服务器,服务器返回符合要求的记录。

服务器端的方法
1
/**//// <summary>
2
/// 总记录数
3
/// </summary>
4
private static int recordCount = 0;
5
6
/**//// <summary>
7
/// 获取分页数据,其中book为自定义的类
8
/// 实际应该传入查询参数,这里只是简单模拟
9
/// </summary>
10
/// <param name="pageSize">页面大小</param>
11
/// <param name="pageIndex">当前页</param>
12
/// <returns></returns>
13
[GenerateScriptType(typeof(Book))]
14
[WebMethod]
15
public static IList<Book> GetBookList(int pageSize, int pageIndex)
16
{
17
// 模拟从数据库返回结果
18
int starRow = pageSize * pageIndex + 1;
19
int endRow = pageSize * (pageIndex + 1);
20
21
if (starRow > recordCount)
22
{
23
starRow = starRow - pageSize;
24
}
25
26
if (endRow > recordCount)
27
{
28
endRow = recordCount;
29
}
30
31
IList<Book> books = new List<Book>();
32
33
for (int i = starRow; i <= endRow; i++)
34
{
35
Book book = new Book("book" + i, "isbn" + i);
36
books.Add(book);
37
}
38
39
return books;
40
}
41
42
/**//// <summary>
43
/// 实际情况应该是从数据库获取总记录数,并且需要有传入参数
44
/// 这里只随机返回一个数字
45
/// </summary>
46
/// <returns></returns>
47
[WebMethod]
48
public static int GetListCount()
49
{
50
recordCount = new Random(DateTime.Now.Millisecond).Next(1, 10000);
51
return recordCount;
52
}

客户端脚本
1
<script language="javascript" type="text/javascript">
2
// 当前页
3
var currentPageIndex = 0;
4
// 总记录数
5
var recordCount = 0;
6
// 总页数
7
var pageCount = 0;
8
// 页面初始大小
9
var pageSize = 10;
10
11
function pageLoad()
12
{
13
// 调用页面的方法获取总记录数
14
PageMethods.GetListCount(onGetListCount);
15
}
16
17
function onGetListCount(result, context, MethodName)
18
{
19
// 处理记录数,计算总页数
20
recordCount = result;
21
calculatePageCount();
22
23
// 调用页面方法获取分页记录
24
PageMethods.GetBookList(pageSize, currentPageIndex, onGetBookListSucceeded);
25
}
26
27
// 计算页数
28
function calculatePageCount()
29
{
30
pageCount = recordCount / pageSize;
31
if (recordCount % pageSize != 0)
32
{
33
pageCount++;
34
pageCount = Math.floor(pageCount);
35
}
36
}
37
38
// 处理服务端返回的查询记录
39
function onGetBookListSucceeded(result, context, methodName)
40
{
41
var contentBuilder = new Sys.StringBuilder("<table border='1' width='100%'><tr><td>book name</td><td>ISBN</td></tr>");
42
for (var i = 0; i < result.length; i++)
43
{
44
contentBuilder.appendLine(String.format("<tr><td>{0}</td><td>{1}</td></tr>", result[i].Name, result[i].ISBN));
45
}
46
contentBuilder.appendLine("</table>");
47
contentBuilder.appendLine(createPageNavigation());
48
$get("divRecords").innerHTML = contentBuilder.toString();
49
}
50
51
// 生成分页页脚分页信息
52
function createPageNavigation()
53
{
54
var pageNaviBuilder = new Sys.StringBuilder("<div class='page'>");
55
var firstPage = "<a><font face='webdings' title='首页' class='navigator' onclick='toPage(0)'>9</font></a> ";
56
57
var previousPage = "<a onclick='toPage(--currentPageIndex)' class='navigator'><font face='webdings' title='上一页'>7</font></a>";
58
if (currentPageIndex == 0)
59
{
60
previousPage = "<a disabled><font face='webdings' title='上一页'>7</font></a>";
61
}
62
63
var nextPage = "<a onclick='toPage(++currentPageIndex)' class='navigator'><font face='webdings' title='下一页'>8</font></a>";
64
if (currentPageIndex == pageCount - 1)
65
{
66
nextPage = "<a disabled><font face='webdings' title='下一页'>8</font></a>";
67
}
68
69
var lastPage = "<a onclick='toPage(pageCount - 1)' class='navigator'><font face='webdings' title='末页'>:</font></a>";
70
71
pageNaviBuilder.appendLine(String.format("第{0}页/共{1}页 共{2}条记录 ", currentPageIndex + 1, pageCount, recordCount));
72
pageNaviBuilder.appendLine(createPageSizeList());
73
pageNaviBuilder.appendLine(firstPage);
74
pageNaviBuilder.appendLine(previousPage);
75
pageNaviBuilder.appendLine(nextPage);
76
pageNaviBuilder.appendLine(lastPage);
77
78
return pageNaviBuilder.toString();
79
}
80
81
// 生成页面大小的下拉选择列表
82
function createPageSizeList()
83
{
84
var pageSizeBuilder = new Sys.StringBuilder("每页<select onchange='onPageSizeChanged(this)'>");
85
// 生成下拉选项
86
for (var i = 1; i <=5; i++)
87
{
88
if (i * 10 != pageSize)
89
{
90
pageSizeBuilder.appendLine(String.format("<option value='{0}'>{0}</option>", i * 10));
91
}
92
else
93
{
94
// 设置选中项为当前的页面大小
95
pageSizeBuilder.appendLine(String.format("<option selected value='{0}'>{0}</option>", i * 10));
96
}
97
}
98
pageSizeBuilder.appendLine("</select>行 ");
99
return pageSizeBuilder.toString();
100
}
101
102
// 给定指定页数获取分页数据
103
function toPage(pageIndex)
104
{
105
if (pageIndex >=0 & pageIndex <= pageCount - 1)
106
{
107
PageMethods.GetBookList(pageSize, pageIndex, onGetBookListSucceeded);
108
currentPageIndex = pageIndex
109
}
110
}
111
112
// 改变页面大小时重新计算页面大小和设置当前页
113
function onPageSizeChanged(sender)
114
{
115
var newPageSize = parseInt(sender.options[sender.selectedIndex].innerText);
116
117
var newPageIndex = (currentPageIndex + 1) * pageSize / newPageSize - 1;
118
if ((currentPageIndex + 1) * pageSize % newPageSize != 0)
119
{
120
newPageIndex++;
121
newPageIndex = Math.floor(newPageIndex);
122
}
123
124
currentPageIndex = newPageIndex;
125
pageSize = newPageSize;
126
127
calculatePageCount();
128
129
if (currentPageIndex > pageCount - 1)
130
{
131
currentPageIndex = pageCount - 1;
132
}
133
134
PageMethods.GetBookList(pageSize, currentPageIndex, onGetBookListSucceeded);
135
}
136
137
</script>
还可以加入加载等待的页面,以及美化一下。另外这里没有实际访问数据库,也没有传入参数,这些都可以扩展,觉得比较适用于显示固定记录数或变动不大的查询。
完整代码