最近在學習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>