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.更利于表示层按各种要求展示,表示层想怎么玩就怎么玩。爽!

猜你喜欢

转载自www.cnblogs.com/ldq678/p/9210575.html
今日推荐