前端攻城狮---AJAX(3)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gaoyouhuang/article/details/81738859

在ajax(2)中,我们讲解了一些基本常见的表单请求,接下来我们在延伸一下ajax的其他知识点吧

AJAX&表单序列化提交

好比注册界面,那么多的组件,那么多的数据,我们不可能一个个去getElementById吧,还要组织数据且将数据拼成$连接的string,太麻烦 太费事,所以我们需要用该方法,大大的简化了ajax请求的操作。先上代码

//样式部分 
<form action="" id="biaodan">
      <p>
          <label>请输入姓名
            <input type="text" name="userName"/>
          </label>
      </p> 
      <p>
            <label>请输入密码
              <input type="password" name="psw"/>
            </label>
        </p> 
      <p>
            请选择性别
              <input type="radio" name="gender" value="男"/>男
              <input type="radio" name="gender" value="女"/>女
         
        </p> 
        <p>
                请选择你的爱好
                  <input type="checkbox" name="hobby" value="足球"/>足球
                  <input type="checkbox" name="hobby" value="篮球"/>篮球
                  <input type="checkbox" name="hobby" value="打豆豆"/>打豆豆
                  <input type="checkbox" name="hobby" value="编程"/>编程
             
        </p> 
        <p>
            请选择你所在省份
            <select name="prov" id="prov">
                <option value="江苏">江苏</option>
                <option value="广东">广东</option>
                <option value="湖南">湖南</option>
            </select>
        </p>
        <p>
            请谈谈你的建议
            <textarea name="message" id="" cols="30" rows="10"></textarea>
        </p>
        <p>
            <input type="button" value="点击提交" id="btn"/>
        </p>
   </form>
 <script>//js部分
        // 找到相关元素
        var biaodan = document.getElementById("biaodan");
        var btn = document.getElementById("btn");
        // 注册事件
        btn.onclick  = function() {
            // 获取所有表单控件
            var eles = biaodan.elements;
            var res = [];  // k=v&k=v&k=v
            // 循环遍历所有的表单控件
            for(var i=0; i<eles.length; i++) {
                var ele = eles[i];
                switch(ele.type) {
                    case "button":
                    case "submit":
                    case "reset":
                             break;
                    case "text":
                    case "password": 
                    case "textarea": 
                       res.push(ele.name+"="+ele.value);
                       break;
                    case "radio": 
                    case "checkbox": 
                       ele.checked&&res.push(ele.name+"="+ele.value); 
                       break;
                    case "select-one":
                         var options = ele.getElementsByTagName("option");     
                         for(var j=0; j<options.length; j++) {
                            options[j].selected&&res.push(ele.name+"="+options[j].value);
                         }
                }
            }
            console.log(res.join("&"));
        }
   </script>

咱们来看看一些关键代码

biaodan.elements

就是获取form表单下,所有的表单元素子空间。

ele.type

为了去判断表单元素的类型,因为想按钮这种是没有提交的数据的,需要进行过滤

select-one

select-one对应的是select,比较特殊,不想其他的类型同type一样。

我们再结合switch,在筛选的同时,将数据进行拼接

string转json

因为接口返回的数据是string类型,绝大部分我们需要将string转成json,便于开发和解析,下面我们来讲讲几种string转json对象的方式

方法1:eval方法

           var json = eval( "("+data+")");

上面的data就是一个string字符串

方法2:new Function()

//使用1        
var fn = new Function("for(var i=1; i<=100; i++) {console.log(i);}");
fn();
//使用2
var data = new Function("return"+data)();
console.log(typeof data);

我们先来分析一下使用1,

在Function里面,我们可以放置一段js代码的字符串,那么那段js代码的字符串,将会被执行,我们可以看到会有100个log日志

使用2,

这里的data是一个字符串,将其return,则返回的是一个json对象

方法3:Json的方法

JSON.parse("string")  字符串--->json
JSON.stringify(json对象) json--->字符串

jquery

jquery&ajax方法

get请求

            $.get("1.json",{"id":4,"name":"李伟"},function(data) {
                console.log(typeof data);
            }); 
            $.get("1.json?id=4&name=阿伟",function(data) {
                console.log(data);
            });

我们看到两种请求地址,一种是带数据,一种是不带数据。若是带数据的,则第二个参数是一个借口调用的回调消息;若不带数据,则第二个参数是请求时的数据,第三个参数是回调消息。这里的数据已经是json对象了,我们无需再转换。

post请求

            $.post("1.json",{"id":5,"name":"lucy"},function(data) {
                console.log(data);
            }); 

其实和get请求没什么区别,只不过是post方法罢了。

通用请求

            $.ajax("b.json",{
                // 请求类型
                "type":"get",
                // 传到服务器上的数据
                "data": {
                    "name":"xiaohong",
                    "age":22
                },
                // 成功要做的事
                "success":function(data) {
                    console.log(data);
                },
                "error":function(XMLHttpRequest,textStatus,errorThrown) {
                    console.log(errorThrown);
                }
            });

$.ajax是一个通用的方法,其实一共就只有两个参数,一个是请求地址,一个是对象,里面包含了请求的数据、方式、回调结果。

我们来分析一个第二个参数

      type表示请求方式:get/post

      data表示请求的数据,是一个json对象

      success表示请求成功的回调

      error表示请求失败的回调

jquery#表单序列表

如果我们用jquery去处理表单序列化,那么会比js原始方法分别很多很多,几行代码搞定

 $("#btn").click(function() {
            // 对form标签调用serialize()方法
            var str = $("#biaodan").serialize();
            console.log(str);
            $.get("check.php?"+str,function(data) {})
        });

从代码中一目了然,一个id是biaodan的表单,通过jquery去获取该对象,并且调用serialize()方法,那个str就是一个string,并且符合请求的数据结构,以&连接。是不是快很多?

ajax的缓存问题

ajax存在着很严重的缓存问题,假如get两次请求,都是同一个url,带着同样的参数,那么即使服务器返回200,也会被当304那样缓存,有些浏览器处理,有些浏览器没有处理。

解决方案

      在请求地址后面加个随机数/时间戳

        $.ajax("1.json?x="+Date.parse(new Date()),{
                // 请求类型
                "type":"get",
                // 传到服务器上的数据
                "data": {
                    "name":"xiaohong",
                    "age":22
                },
                // 成功要做的事
                "success":function(data) {
                    console.log(data.content[1].name);
                },
                "error":function(XMLHttpRequest,textStatus,errorThrown) {
                    console.log(errorThrown);
                }
            });

我们看到了请求地址的后缀吧----->x=时间戳,虽然服务器不去处理这个x参数,但是保证了每次的请求是不同了,就避免了ajax的缓存问题。

模板引擎的使用

什么模板?那个模板?其实ajax的模板就涉及到了实际开发中。试问一下,加入我们请求了一个地址返回了很多数据,我们需要将这些数据显示成一个列表,这时候我们要怎么做?就用到了模板,将一个item做成模板,然后循环的去显示数据,就变成了一个列表。可能很抽象,咱们一步一步来分析。

模板引擎实例1

我们请求接口,将返回的数据以加载到 li 里面。

   $("#btn").click(function() {
            $.post("1.json",{"id":5,"name":"lucy"},function(data) {
                //console.log(data);
                for(var i=0; i<data.content.length; i++) {
                    var $li = $("<li></li>");
                    $li.html(data.content[i].id+":"+data.content[i].name);
                    $("ul").append($li); 
                }
            });      
        });
{
    "content":[{
         "id":1,
         "name":"小红"
    },{
        "id":2,
        "name":"小花"
    },
    {
        "id":3,
        "name":"小明"
    }
    ]
}

下面就是返回的json数据,我们去循环并取出id name 去加载到 li 中,

我们去创建一个 li 对象,并添加数据,最后添加到 ul 里面。这里的 li 就是模板,我们给这个模板去加载不同的数据,最后添加到要显示的容器里。

模板引擎实例2

模板1是视图的模板,那么模板2就是数据的模板,比如说我们需要给指定的数据,指定的位置,去替代接口返回的指定的数据,要怎么做?下面我们来看看

       var str = "今天是个@rizi@的日子,我的心情非常@mood@";
        // 数据字典
        var dictionary = {
            "rizi": "伟大",
            "mood":"激动"
        }
        function compile(templateString,dictionaryObj) {
             return templateString.replace(/\@(\w+)\@/g,function(match,$1,index,string) {
                  return dictionary[$1];
           }) 
        }

        str = compile(str,dictionary);
        document.getElementsByTagName("h1")[0].innerHTML = str;

首先 str,就是要改变的数据,@rizi@ @mood@ 表示的是修改数据的模板,dictioinay就表示接口返回的数据。其实我们发现rizi mood 对应的是接口返回数据的key,所以这数据的模板不是随便命名的,接着compile方法去替换到接口返回数据里对应的值。

模板引擎实例3

如调用接口显示表格,我们结合实例1和实例2 去综合使用

  <script type="text/template" id="template">
        <tr>
            <td>@xuehao@</td>
            <td>@xingming@</td>
            <td>@age@</td>
            <td>@score@</td>
        </tr>
    </script>
    <script src="js/jquery.js"></script>
    <script>
        // 1 模板字符串
         var str = $("#template").html();
         // 2 根据模板字符串生成数据绑定函数
         $.get("students.json",function(data) {
             for(var i=0; i<data.students.length; i++) {
                 var student = data.students[i];
                 var DOMString = compile(str,student);
                 // 追加到表格末尾
                 $("#tb").append(DOMString);
             }  
         });
         function compile(templateString,dictionaryObj) {
             return templateString.replace(/\@(\w+)\@/g,function(match,$1,index,string) {
                  return dictionaryObj[$1];
           }) 
        }
    </script>

id为template的script就是我们的模板,里面的数据用@符号包裹,对应的分别是数据的key,然后我们去替换,对应的数据,再拼接到$("#tb")的对象里面。这样就完成了模板引擎+ajax的综合使用。其实我们还可以使用underscore.js这个库,里面提供了模板引擎的方法,以便于我们快速开发。看下面的模板引擎4

模板引擎实例4

  <script type="text/template" id="template">
        <tr>
            <td><%=xuehao%></td>
            <td><%=xingming%></td>
            <td><%=age%></td>
            <td><%=score%></td>
        </tr>
    </script>
    <script src="js/underscore.js"></script>
    <script src="js/jquery.js"></script>
    <script>
        // 1 模板字符串
         var str = $("#template").html();
         // 2 根据模板字符串生成数据绑定函数
         var compile = _.template(str);
         // 拿到数据
         $.get("students.json",function(data) {
             _.each(data.students,function(dictionary) {
                   var domStr = compile(dictionary); 
                   // 追加到表格末尾
                 $("#tb").append(domStr);
             });
         });
    </script>

主要代码就这几部

  var compile = _.template(str);   str表示模板字符串  

  var domstr = compile(dictionary);  dictionary表示数据

_.each(),则是underscore的一个循环遍历方法。

Jsonp

首先ajax不支持跨域,比如说我现在的服务器是php,地址比如说是192.168.9.9,那么我只能请求该地址下的请求,不能去访问www.qq.com。

          $.get("http://www.baidu.com",function(data) {
              alert(data);
          });

则会报错,那么我们要解决的问题就是如果去跨域请求。大家js库肯定使用过,可以应用本地的js文件,也可以使用域名去下载js来使用。关键来了,为什么script标签就可以去跨域?而网络请求就不行?Jsonp的发明者发现了这一点特性,script.src支持跨域,就有了Jsonp。

Jsonp的原理

一下是我们三个案例使用的数据,括号内的表示跨域请求回来的数据

// 函数调用语句 数据作为函数的实参
fun({
    "students":[{
        "xuehao":100001,
        "xingming":"zs",
        "age":22,
        "score":78
    },{
        "xuehao":100002,
        "xingming":"wh",
        "age":22,
        "score":78
    },{
        "xuehao":100003,
        "xingming":"zn",
        "age":22,
        "score":78
    }]
});

案例1

   <script>
                // 定义一个函数
        function fun(data) {
                   console.log(data);
        }
    </script>
    <script src="http://www.gggjsonp.js"></script>
    

我们利用script.src的跨域特性,去发起跨域请求。

然后在jsonp.js里面去调用window的方法fun,将跨域请求回来的数据传到window中,从而去显示。这里的www.gggjsonp.js不是在同一个服务器下的,就像我们去使用不同的js库一样去下载。

案例2

         function fun(data) {
             console.log(data);
         }

         var btn = document.getElementById("btn");
         btn.onclick = function() {
            // <script src="jsonp.txt"><\/script> 
            var oScript = document.createElement("script");
            document.body.appendChild(oScript);
            oScript.src="http://www.gggjsonp.js";
         }

我们结合了实际应用,去手动创建script,设置src发去跨域请求。

案例3

 jsonp("jsonp.txt","fun",function(data) {
           console.log(data);
        });
        // 编写一个轮子 以后进行jsonp进比较方便
        function jsonp(URL,callbackname,callback) {
             window[callbackname] = callback;
             // 创建script元素
             var oScript = document.createElement("script");
            // 添加节点
             document.body.appendChild(oScript);
            oScript.src= URL;
            // 删除
            document.body.removeChild(oScript);
        }

我们对jsonp的请求过程进行了封装。

案例4

$.ajax({
  dataType: 'jsonp',
  url: 'http://www.a.com/user?id=123',
  success: function(data){
    //处理data数据
  }
});

因为jquery 也提供了jsonp的调用方法。

ajax的知识点已经讲解完毕,后面会讲解瀑布流的布局结合ajax达到上拉加载的效果,若表达有误请指出,望共同进步。

猜你喜欢

转载自blog.csdn.net/gaoyouhuang/article/details/81738859