1. 程式人生 > >AJAX(四)實例 -- json格式數據

AJAX(四)實例 -- json格式數據

net IE 希望 語言 dom 來看 .net dom操作 服務端

  本期來講解在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格式數據