zoukankan      html  css  js  c++  java
  • 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.更利于表示层按各种要求展示,表示层想怎么玩就怎么玩。爽!

       四、为什么是JSON?

      因为json有以下几个显而易见的好处:  

    1. 简单,结构清晰
    2. 省空间,基本没什么浪费的字符

    3. 标准,主流的都用它,也都支持它

    4. 语言无关,任何语言都能轻松搞它

      其实在json兴起之前,用的更多的是XML格式的数据,相比较来说,json更轻量级,解析时更简单。

      by the way,如果你的后台传递过来的是XML格式数据,那么通过异步对象XMLHttpRequest去获取响应报文时,就需要使用另一个api,代码大致如下:  

    var xmlResp = xhr.responseXML;

      至于javascript如何解析XML数据,其实就跟DOM操作差不多,用的也还是那几个API,大家试试就会了。

  • 相关阅读:
    Entity Framework 6 Recipes 2nd Edition(9-4)译->Web API 的客户端实现修改跟踪
    Entity Framework 6 Recipes 2nd Edition(9-3)译->找出Web API中发生了什么变化
    Entity Framework 6 Recipes 2nd Edition(9-2)译->用WCF更新单独分离的实体
    Entity Framework 6 Recipes 2nd Edition(9-1)译->用Web Api更新单独分离的实体
    jar包和war包的介绍和区别
    软件设计-高内聚耦合(转)
    Android中的dp,px以及wrap_content的实际展示效果
    Eclipse编辑器样式修改
    对TextView设置drawable,用setCompoundDrawables方法实现
    Android调用本机应用市场,实现应用评分功能
  • 原文地址:https://www.cnblogs.com/ldq678/p/9210575.html
Copyright © 2011-2022 走看看