最近在学习Ajax,这真是个好东西啊,能大大调高用户的体验,异步式的开发着实很爽,前段时间刚学asp.net webform时候,没有ajax有很多操作要不同的页面进行操作,要不停的跳转,如果页面再有一堆服务端控件,着实不爽,体验特别的不舒服.Ajax是什么东西,我就不说了,大家都知道,本人刚学这个,发现写js代码十分的不熟,以后要多练练,下面我就分享我学习过程中的一些实际运用Ajax的Demo,着实没什么技术,纯粹的分享,让没有学过Ajax的能够了解Ajax的一些基本用法,大家共同学习,共同进步,Demo很简单利用AJAX的CRUD和分页等..
加载数据跟分页
首先我们自己搭建个表,具体的字段可以自己来设置,然后增加点数据即可,自己写分页存储过程,这个分页存储我直接用的代码生成器生成,其实大家可以根据自己的需求来写分页,然后我是用的三层,如果自己写分页存储过程,可以自己写Dal层的代码,会比较麻烦,但是写一次以后都能用了..我偷懒了直接用动软那套了.然后分页还需要一个生成html字符串的代码,用于在前台生成页码超链接,我本来想把它改成JS方法的,但是没成功,js实在烂,这样可以再后台穿参数过去即可,不需要传html标签字符串,增加传输量,具体的如下:
public static string ShowPageNavigate(int pageSize, int currentPage, int totalCount)
{
string redirectTo = "";
pageSize = pageSize == 0 ? 3 : pageSize;
var totalPages = Math.Max((totalCount + pageSize - 1) / pageSize, 1); //总页数
var output = new StringBuilder();
if (totalPages > 1)
{
if (currentPage != 1)
{//处理首页连接
output.AppendFormat("<a class='pageLink' href='{0}?pageIndex=1&pageSize={1}'>首页</a> ", redirectTo, pageSize);
}
if (currentPage > 1)
{//处理上一页的连接
output.AppendFormat("<a class='pageLink' href='{0}?pageIndex={1}&pageSize={2}'>上一页</a> ", redirectTo, currentPage - 1, pageSize);
}
else
{
// output.Append("<span class='pageLink'>上一页</span>");
}
output.Append(" ");
int currint = 5;
for (int i = 0; i <= 10; i++)
{//一共最多显示10个页码,前面5个,后面5个
if ((currentPage + i - currint) >= 1 && (currentPage + i - currint) <= totalPages)
{
if (currint == i)
{//当前页处理
//output.Append(string.Format("[{0}]", currentPage));
output.AppendFormat("<a class='cpb' href='{0}?pageIndex={1}&pageSize={2}'>{3}</a> ", redirectTo, currentPage, pageSize, currentPage);
}
else
{//一般页处理
output.AppendFormat("<a class='pageLink' href='{0}?pageIndex={1}&pageSize={2}'>{3}</a> ", redirectTo, currentPage + i - currint, pageSize, currentPage + i - currint);
}
}
output.Append(" ");
}
if (currentPage < totalPages)
{//处理下一页的链接
output.AppendFormat("<a class='pageLink' href='{0}?pageIndex={1}&pageSize={2}'>下一页</a> ", redirectTo, currentPage + 1, pageSize);
}
else
{
//output.Append("<span class='pageLink'>下一页</span>");
}
output.Append(" ");
if (currentPage != totalPages)
{
output.AppendFormat("<a class='pageLink' href='{0}?pageIndex={1}&pageSize={2}'>末页</a> ", redirectTo, totalPages, pageSize);
}
output.Append(" ");
}
output.AppendFormat("第{0}页 / 共{1}页", currentPage, totalPages);//这个统计加不加都行
return output.ToString();
}
有了这个类,我们下面还是着手第一件事:加载数据到页面,这是我用的纯html页面跟一般处理程序来处理,避免走webform那一陀的生命周期,首先需要一个展示UserList的页面和一个加载数据的一般处理程序LoadUserList.ashx,展示页面里面可以用一个表格来展示了,首先我们在页面前面引用jquery跟jquery-UI等需要用到的文件,再写个table,具体如下:
<body>
<table id="userListTab">
<tr>
<th>编号
</th>
<th>登录名
</th>
<th>电话
</th>
<th>邮箱
</th>
<th>操作
</th>
</tr>
</table><br /><!--页面分页 -->
<div id="pageNavigation"></div>
pageNavigation层用于放分页导航.具体的后台代码如下:
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
int pageSize = context.Request["pageSize"] == null ? 5 : int.Parse(context.Request["pageSize"]);
int pageIndex = context.Request["pageIndex"] == null ? 1 : int.Parse(context.Request["pageIndex"]);
int totalCount = 0;
totalCount = new BLL.HKSJ_USERS().GetRecordCount(string.Empty);
List<Model.HKSJ_USERS> users = new List<Model.HKSJ_USERS>();
DataSet ds = new BLL.HKSJ_USERS().GetListByPage(string.Empty, "Id", (pageIndex - 1) * pageSize + 1, pageIndex * pageSize);
users = new BLL.HKSJ_USERS().DataTableToList(ds.Tables[0]);
var pageNavigation = Common.LaomaPager.ShowPageNavigate(pageSize, pageIndex, totalCount);
var data = new { trData=users,pageNavigation };
string htmlString = new JavaScriptSerializer().Serialize(data);
context.Response.Write(htmlString);
}
当页面加载的时候发送一个异步请求到后台,默认加载页面时没有context.request["pageSize"]跟["pageIndex"]这个参数的,我们默认显示5个跟第1页,后面是取得根据具体分页等到的实体,我把他们放在list<model>中,方便后面序列化成json对象,然后根据pageSize跟pageIndex得到回传回去具体的html代码(就是一些a标签),把pageNavigation and Users序列化Json对象,我直接用JavaScriptSerializer来序列化,当然你可以自己拼接字符串(比较灵活,就是比较麻烦,有很多转义)...后台大致写好了,下面开始写前台的js代码,我觉的我们一定要会调试js代码,不然写js代码特别麻烦,不像vs写C#代码出错各种提示,后面会说点我自己的调试的方法,写js代码要注意很多,我自己也写的不熟,以后要多练练..好下面我们来写前台的代码..思路具体如下:
- 首先页面加载发送个一个异步请求到后台,取得数据(json),在前台动态生成html标签(也可以在后台拼接好了html再传到前台,但是增加传输量,这就是我想把那个类改成js版的原因)
- 将生成的html代码append到你所想展示的地方,我是展示到table里面,把这个两个步骤封装成一个方法function
- 加载数据算是完成,下面开始加载分页导航,同样页面加载的时候发送一个请求到后台,这里我都请求同一个一般处理程序,因为返回的数据两者都包含了.
- 下面要给分页导航的a标签注册事件,并且不执行跳转,同样是也异步化的
具体代码如下:
function InitUserListByPage(requestData) {
//每次加载先删除再加载
$('#userListTab tr:gt(0)').remove();
//异步请求
$.getJSON("LoadUserList.ashx", requestData, function (data) {
for (i = 0; i < data.trData.length; i++) {
var htmlString = "<tr><td id='ID'>" + data.trData[i].ID + "</td><td id='LoginName'>" + data.trData[i].LoginName + "</td><td id='Phone'>" + data.trData[i].phone + "</td><td id='Mail'>" + data.trData[i].Mail + "</td><td><a href='DeleteUser.ashx?id=" + data.trData[i].ID + "' class='DeleteLink' userId=" + data.trData[i].ID + ">删除</a></td><td><a href='UpdateUser.ashx?id=" + data.trData[i].ID + "' class='UpdateLink' userId=" + data.trData[i].ID + ">添加</a></td><tr>";
$('#userListTab').append(htmlString);
}
DeleUser();
Edituser();
});
}
function InitPageNavigation(requestData) {
$.getJSON("LoadUserList.ashx", requestData, function (data) {
var htmlString = data.pageNavigation;
$("#pageNavigation").html(htmlString);
$(".pageLink").click(function () {
var strHref = $(this).attr("href");
strHref = strHref.substring(strHref.lastIndexOf('?') + 1, strHref.length);
InitPageNavigation(strHref);
InitUserListByPage(strHref);
return false;
})
})
}
关于页面分页有些地方要说下:strHref是用来获取发送到后台的参数:pageSize=1&pageIndex=5 这个字符串的,为超连接注册事件,首先获得所有的超链接(这个当前页面没有获得,因为当前的页面的class不是pageLink),点击后我们要重新加载数据跟分页,这里自己调用自己,联合上面给出的加载数据的方法,是很容易理解的,也就是是重新获取数据跟分页.参数requsetData表示的是pageSize=1&pageIndex=5这个样子的,如果没有后台也做了处理默认给你第一页跟5条数据,这一般加载的时候才传个空数据.加载的代码如下,直接调用两个方法即可
$(function () {
//init table
$('#EditUser').css("display", "none");
InitUserListByPage();
//innit pagenavagation
InitPageNavigation();
这样根据页码跟页数得到数据,并且页面不用跳转:具体效果如下:不足之处在于点击当前页还是会刷新,这个很好解决,给当前也注册事件就OK了~
删除数据
下面所要做的操作就是删除数据,这个就简单了,发个一个异步请求到后台,删除即可,我的做法就是在生成表格后加个删除超链接,为超连接都加上个class="deleteLink"跟"UserID" =前面或者的ID,这样就方便传递ID跟或者a标签,需要注意的就是给a标签注册事件事件时必须在加载表格后再注册,不然会失效的,同样的我们封装成一个方法function:
function DeleUser() {
$('.DeleteLink').click(function () {
var userId = $(this).attr("userId");
var td = $(this);
if (confirm("are you sure")) {
$.get("DeleteUser.ashx", { id: userId }, function (data) {
if (data = "true") {
td.parent().parent().hide("slow");
} else {
alert("Error");
}
});
}
return false;
});
}
一般删除都需要有个确认,这里用confirm来确定,必须return false,后台代码很简单根据Id删除就行了,返回true or false
添加数据
如同删除一样在后面加上添加超链接,并给超连接注册事件,这里我是点击,然后弹出个层来给用户修改,上面展示数据,有个修改按钮,并且给按钮注册事件,也就是给后台修改同样是异步,弹出个遮罩层我直接用jquery-ui来了,自己写也能写,但又要写一陀.刚开始的时候,我们首先让修改层隐藏,点击超链接,层出现,并把数据显示出来,后台修改也要把原来的数据都查数来,因为有些数据是不会给用户看的,更新的时候统统要更新的,后台代码逻辑很简单.
<!--修改层-->
<div id="EditUser">
<table>
<tr>
<td>编号</td>
<td>
<input type="hidden" name="hidden" value=" " id="hidden" />
<span id="txtShowId"></span></td>
<td>登录名</td>
<td>
<input type="text" name="LoginNameShow" value=" " id="LoginNameShow" /></td>
<td>电话</td>
<td>
<input type="text" name="PhoneShow" value=" " id="PhoneShow" /></td>
<td>邮箱</td>
<td>
<input type="text" name="MailShow" value=" " id="MailShow" />
</td>
<td colspan="2">
<input type="button" name="Update" value="Update" id="Update" /></td>
</tr>
</table>
</div>
这里面需要个隐藏域来向后台传递ID,超链接的注册事件如下:
//注册添加用户事件
function Edituser() {
$('.UpdateLink').click(function () {
var id = $(this).attr('userId');
$.getJSON("GetUserInfoById.ashx", { id: id }, function (data) {
$("#hidden").val(data.ID);
$("#txtShowId").text(data.ID);
$("#LoginNameShow").val(data.LoginName);
$("#MailShow").val(data.Mail);
$('#PhoneShow').val(data.phone);
})
//$("#hidden").val(id);
//$('#txtShowId').text(id);
$("#EditUser").dialog({//设置div为dialog
autoOpen: false,
title: "注册用户",
height: 400,
width: 1000,
modal: true
});
$("#EditUser").dialog("open");
return false;
})
}
这里显示数据我是直接发个请求到后台根据ID或者数据,然后显示到层上,下面就是给Update注册事件了:
function UpdateUser() {
$('#Update').click(function () {
var JsonData = {
Id: $("#hidden").val(),
Phone: $('#PhoneShow').val(),
LoginName: $("#LoginNameShow").val(),
Mail: $("#MailShow").val()
}
$.get("UpdateUser.ashx", JsonData, function (data) {
if (data = "true") {
$("#EditUser").dialog("close");
InitUserListByPage();
}
})
})
}
具体效果如下:
其实添加一般都是用户注册的,我们可以不用一个隐藏的层,我们可以用一个iframe指向注册页面,点击超链接,然后iframe显示,用户注册.如果要用iframe指向一个写好的页面来实现无刷新效果的话,ifame不能操作父页面的元素,这就带来了不方便.我们一般是这样父类提供一个属性或者方法,你可以调用方法来更改父类的私有字段,这里我们在原页面加入一个方法:
function afterRegistSuccess() {
$("#showRegistUser").dialog("close"); //弹出对话框
initUserTable();//绑定表格
}
iframe层为:
<!-----------------------弹出的添加用户的对话框----------------------->
<div id="showRegistUser">
<iframe scrolling="yes" width="100%" height="100%" frameborder="0" src="RegistUser.htm"></iframe>
</div>
然后iframe指向页面的代码也要处理: window.parent.window指等就是我们父页面,然后调用方法即可关闭层!
$.post("Regist.ashx", strRequestData, function (data) {
if (data == "ok") {
window.parent.window.afterRegistSuccess();
}
});
总结
写js代码一定要注意各种细节,其实逻辑不复杂,关键是有些地方少这个少那个,大小写,能否取到ID等等,js好难调试.下面我说下我的调试方式,我一般使用chrome浏览器的开发人员工具来调,这样可以看到很多东西,包括返回的json数据,请求报文返回报文等等,也可以调试JS代码,写JS不难调试难,个人感觉.就拿上面window.parent.window对象,我对这个很抽象,不知道写的对不对,起初写的window.parent,后来运行起来没反应,我就用调试的过程加上个window才调出来,具体如下:
我先找的两个对象..都是window...然后我再找谁有这个afterRegistSuccess方法,结果一看就知道.这个跟VS一样可以设置断点,右上的+号可以添加你想看得元素,如果你js代码有错误,chrome也会帮你指出的,着实强大!总之我们要不仅仅要会写更要出错了知道哪里出错,再改之.下面给出整个前台代码 结合起来看更能理清自己的思路,后台的就不量出来了,就是crud,希望大家共同学习进步!
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>UserList</title>
<link href="http://www.cnblogs.com/style/tableStyle.css" rel="stylesheet" />
<link href="http://www.cnblogs.com/../Content/Css/ui-lightness/jquery-ui-1.8.4.custom.css" rel="stylesheet"
type="text/css" />
<script src="http://www.cnblogs.com/../js/jquery-1.4.2.min.js" type="text/javascript"></script>
<script src="http://www.cnblogs.com/../js/jquery-ui-1.8.4.custom.min.js"></script>
<script>
$(function () {
//init table
$('#EditUser').css("display", "none");
InitUserListByPage();
//innit pagenavagation
InitPageNavigation();
$('#Update').click(function () {
var JsonData = {
Id: $("#hidden").val(),
Phone: $('#PhoneShow').val(),
LoginName: $("#LoginNameShow").val(),
Mail: $("#MailShow").val()
}
$.get("UpdateUser.ashx", JsonData, function (data) {
if (data = "true") {
$("#EditUser").dialog("close");
InitUserListByPage();
}
})
})
});
//load userList
function InitUserListByPage(requestData) {
//每次加载先删除再加载
$('#userListTab tr:gt(0)').remove();
//异步请求
$.getJSON("LoadUserList.ashx", requestData, function (data) {
for (i = 0; i < data.trData.length; i++) {
var htmlString = "<tr><td id='ID'>" + data.trData[i].ID + "</td><td id='LoginName'>" + data.trData[i].LoginName + "</td><td id='Phone'>" + data.trData[i].phone + "</td><td id='Mail'>" + data.trData[i].Mail + "</td><td><a href='DeleteUser.ashx?id=" + data.trData[i].ID + "' class='DeleteLink' userId=" + data.trData[i].ID + ">删除</a></td><td><a href='UpdateUser.ashx?id=" + data.trData[i].ID + "' class='UpdateLink' userId=" + data.trData[i].ID + ">添加</a></td><tr>";
$('#userListTab').append(htmlString);
}
DeleUser();
Edituser();
});
}
//删除用户事件
function DeleUser() {
$('.DeleteLink').click(function () {
var userId = $(this).attr("userId");
var td = $(this);
if (confirm("are you sure")) {
$.get("DeleteUser.ashx", { id: userId }, function (data) {
if (data = "true") {
td.parent().parent().hide("slow");
} else {
alert("Error");
}
});
}
return false;
});
}
//页面分页
function InitPageNavigation(requestData) {
$.getJSON("LoadUserList.ashx", requestData, function (data) {
var htmlString = data.pageNavigation;
$("#pageNavigation").html(htmlString);
$(".pageLink").click(function () {
var strHref = $(this).attr("href");
strHref = strHref.substring(strHref.lastIndexOf('?') + 1, strHref.length);
InitPageNavigation(strHref);
InitUserListByPage(strHref);
return false;
})
})
}
//获得分页标签
function pageNavigation(pageIndex, pageSize, totalCount) {
var redirectTo = "";
var totalPages = Math.max((totalCount + pageSize - 1) / pageSize, 1);
var pageNavi;
if (totalCount > 1) {
if (pageIndex != 1) {
pageNavi = "<a class='pageLink' href=" + redirectTo + "?pageIndex=1&pageSize=" + pageSize + "'>首页</a> ";
} if (pageIndex > 1) {
pageNavi = "<a class='pageLink' href=" + redirectTo + "?pageIndex=" + pageIndex + "&pageSize=" + pageSize + "'>上一页</a> ";
} else {
}
pageNavi = pageNavi + " ";
var currint = 5;
for (var i = 0; i < 10; i++) {
if ((pageIndex + i - currint) >= 1 && (pageIndex + i - currint) <= totalPages) {
if (currint == i) {
pageNavi = pageNavi + "<a class='cpb' href=" + redirectTo + "?pageIndex=" + pageIndex + "&pageSize=" + pageSize + "'>" + pageIndex + "</a> ";
} else {
pageNavi = pageNavi + "<a class='pageLink' href=" + redirectTo + "?pageIndex=" + pageIndex + i - currint + "&pageSize=" + pageSize + "'>" + pageIndex + i - currint + "</a> ";
}
}
pageNavi = pageNavi + " ";
if (pageIndex < totalPages) {
pageNavi = pageNavi + "<a class='pageLink' href=" + redirectTo + "?pageIndex=" + currentPage + 1 + "&pageSize=" + pageSize + "'>下一页</a> "
} else {
}
pageNavi = pageNavi + " ";
if (pageIndex = totalPages) {
pageNavi = pageNavi + "<a class='pageLink' href=" + redirectTo + "?pageIndex=" + totalPages + "&pageSize=" + pageSize + "'>末页</a> "
}
}
return pageNavi;
}
}
//注册添加用户事件
function Edituser() {
$('.UpdateLink').click(function () {
var id = $(this).attr('userId');
$.getJSON("GetUserInfoById.ashx", { id: id }, function (data) {
$("#hidden").val(data.ID);
$("#txtShowId").text(data.ID);
$("#LoginNameShow").val(data.LoginName);
$("#MailShow").val(data.Mail);
$('#PhoneShow').val(data.phone);
})
//$("#hidden").val(id);
//$('#txtShowId').text(id);
$("#EditUser").dialog({//设置div为dialog
autoOpen: false,
title: "注册用户",
height: 400,
width: 1000,
modal: true
});
$("#EditUser").dialog("open");
return false;
})
}
</script>
</head>
<body>
<table id="userListTab">
<tr>
<th>编号
</th>
<th>登录名
</th>
<th>电话
</th>
<th>邮箱
</th>
<th>操作
</th>
</tr>
</table>
<br />
<!--页面分页 -->
<div id="pageNavigation">
</div>
<!--修改层-->
<div id="EditUser">
<table>
<tr>
<td>编号</td>
<td>
<input type="hidden" name="hidden" value=" " id="hidden" />
<span id="txtShowId"></span></td>
<td>登录名</td>
<td>
<input type="text" name="LoginNameShow" value=" " id="LoginNameShow" /></td>
<td>电话</td>
<td>
<input type="text" name="PhoneShow" value=" " id="PhoneShow" /></td>
<td>邮箱</td>
<td>
<input type="text" name="MailShow" value=" " id="MailShow" />
</td>
<td colspan="2">
<input type="button" name="Update" value="Update" id="Update" /></td>
</tr>
</table>
</div>
</body>
</html>