AJAX(四)實例 -- json格式數據
本期來講解在AJAX中使用json格式數據。不過我們先不說json的事,先來做個案例,然後由這個案例我們再來討論為啥要用json數據,以及怎麽用。
一、案例
非常經典,也是非常簡單的AJAX案例,省市聯動。就是在網上常見的,選擇一個省份,然後城市所在的<select>標簽中再動態加載進來所選省份包含的城市選項。
HTML是極其簡單的。為了讓案例更簡單,省份的<select>標簽中的選項都寫死了,其中value代表省份的主鍵id。城市所對應的<select>標簽也是如此,不在贅述。
<body> 省份:<select id="province"> <option value="1">河北</option> <option value="2">河南</option> <option value="3">山東</option> <option value="4">山西</option> </select> 城市:<select id="city"></select> </body>
後臺代碼也是非常簡單的,仍然使用一般處理程序,如下。
其中City是城市實體類,3個字段。
需要簡單說明的是這個一般處理程序,它的思路是:
1.通過QueryString獲取到get請求傳遞過來的proId(省份id)。
2.根據proId從數據庫中獲取到包含的城市(IList<City>)。
3.遍歷這個IList<City>城市集合,然後拼寫成類似於"<option value=‘0100001‘>成都</option><option value=‘0100002‘>綿陽</option>......."這樣的字符串。因為這樣的字符串可以直接放到<select>標簽對的內部,形成該下拉選項框的選項。
public class City { public int Id { get; set; }//城市主鍵 public string Name { get; set; }//城市名字 public int proId { get; set; }//省份的id }
public class citysHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; if (context.Request.HttpMethod.ToUpper() == "GET") { string proId = context.Request.QueryString["proId"]; Citys citys = new Citys(); IList<City> cList = citys.GetCitysByProId(proId); StringBuilder opts = new StringBuilder(); foreach (City c in cList) { opts.Append("<option value=‘" + c.Id + "‘>"); opts.Append(c.Name); opts.Append("</option>"); } context.Response.Write(opts.ToString()); } } public bool IsReusable { get { return false; } } }
接下來是客戶端代碼。當用戶選擇任意一個省份後,觸發該省份下拉框的onchange事件,在該事件中使用AJAX方式,發出get請求,訪問服務端citysHandler.ashx。代碼如下:
代碼沒有太多需要解釋的,由於服務端直接返回的就是拼接好html標簽的字符串,所以直接作為innerHTML放到<select id="city"><select>裏去就可以了,倒是非常簡單。
<script> window.onload = function () { var selProv = document.getElementById("province"); selProv.onchange = function () { if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } var proId = this.value; var url = "citysHandler.ashx" + "?proId=" + proId; xhr.open("get", url, true); xhr.setRequestHeader("If-Modified-Since", "0"); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { var opts = xhr.responseText; var selCity = document.getElementById("city"); selCity.innerHTML = opts; } } xhr.send(null); } } </script>
二、弊端
功能雖然實現了,但是弊端還是挺大的。
1.服務端返回的字符串不光包含需要展示給用戶看的數據,比如城市名字,城市的id,更重要的是這些數據被<option>標簽包住了。換句話說服務端返回的數據不幹凈,或者說不純粹,加載了太多html標簽。這麽做的弊端在於把這個後端的數據接口限制死了,由於<option>只能放在<select>標簽中作為選項用,那麽如果以後客戶希望在一個<table>中展示所有數據,那麽這個後臺的服務就不可重用了。
2.夾雜了很多html標簽後,要傳輸的數據量必定加大,那麽勢必降低程序的性能,至少客戶端的響應速度會變慢,這對於性能控制狂來說是不可接受的。
三、改進--json
json只是一種數據格式,它是從JavaScript的字面量表示法演變過來的,也是JavaScript語言中的一種對象描述方式。它的語法特別簡單:{“key1” : "val1" , “key2” : "val2" , ....... }。它與字面量表示法唯一的區別就是json格式要求所有的key和value都要用雙引號引住,單引號不可以,不引更不可以。
好了,先看服務端的代碼改造吧。只看一般處理程序的PR方法就OK了。
這裏使用了System.Web.Script.Serialization.JavaScriptSerializer對一個集合進行序列化,序列化的結果當然就是一個JSON格式的字符串。
public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; if (context.Request.HttpMethod.ToUpper() == "GET") { string proId = context.Request.QueryString["proId"]; Citys citys = new Citys(); IList<City> cList = citys.GetCitysByProId(proId); System.Web.Script.Serialization.JavaScriptSerializer jss = new System.Web.Script.Serialization.JavaScriptSerializer(); string jsonCitys = jss.Serialize(cList); context.Response.Write(jsonCitys); } }
★ 需要註意的是JSON對象與JSON格式的字符串是有本質不同的。
打個比方:
int i = 12345;
string str = "12345";看上去都是存的12345,但是有本質不同,變量i存的是一個整數,能做算術運算的整數;而變量str裏存的數據看上去也是“12345”,但這是個字符串,不能做算術運算。
如果你還不理解,再來看個例子。
int[ ] arr = {22, 12, 34, 45};很顯然這是個整形數組
“ {22, 12, 34, 45}”,而這個是字符串,只不過跟上邊那個數組“長得”很像罷了。
所以這裏經過.NET提供的JavaScriptSerializer序列化過後的數據,是個字符串,長得樣子大概就是 “[{"Id":1,"Name":"成都","proId":5},{"Id":2,"Name":"綿陽","proId":5},{"Id":3,"Name":"廣元","proId":5}]” 這個樣子。不過看好了,兩頭有“”,這個是個正經八百的字符串,所以,這樣的數據傳遞到前端後,我們需要使用JavaScript的方式,把這個字符串再轉換成JSON對象。
接下來改造前臺JavaScript代碼
只需要看回調函數就可以了,其他地方不需要改。
xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { var opts = xhr.responseText; var selCity = document.getElementById("city"); //selCity.innerHTML = opts; var jsonCitys = JSON.parse(opts); for (var i = 0; i < jsonCitys.length; i++) { var opt = document.createElement("option"); opt.setAttribute("value", jsonCitys[i].Id); opt.innerHTML = jsonCitys[i].Name; selCity.appendChild(opt); } } } xhr.send(null);
關鍵點是這條語句:var jsonCitys = JSON.parse(opts); JSON.parse()是JavaScript提供的1個API,它的作用是把一個JSON格式的字符串,轉化成一個JSON對象。當然,如果傳遞過來的字符串是一個由多個JSON格式對象組合成的數組樣式的字符串,就比如我們這裏就是如此:“[{"Id":1,"Name":"成都","proId":5},{"Id":2,"Name":"綿陽","proId":5},{"Id":3,"Name":"廣元","proId":5}]” 。我們從後臺得到的數據,引號內部首先是一對 [ ] ,這個方括號顯然就是js中數組的符號了。
那麽這種情況下,JSON.parse()會把這個字符串解析成由多個JSON對象組成的一個JavaScript數組。然後我們就能用for循環遍歷它了。
接下來的DOM操作,就不必細說了。
再回頭看這個例子,經過改造後,後臺傳遞來的數據是“純粹的”,不帶有任何表示層的東西,這樣帶來的好處:1.要傳輸的數據量小,輕量化了。2.更利於表示層按各種要求展示,表示層想怎麽玩就怎麽玩。爽!
AJAX(四)實例 -- json格式數據