Ajax初步认识
最近在学习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>