AJAX

AJAX是什么?

AJAXAsynchronous Javascript And XML)翻译成中文就是异步JavascriptXML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。

AJAX还有一个最大的特点就是,当服务器响应时,不用刷新整个浏览器页面,而是可以局部刷新。这一特点给用户的感受是在不知不觉中完成请求和响应过程。可总结为

  • 与服务器异步交互
  • 浏览器页面局部刷新

那同步交互和异步交互的区别是什么?

  • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求
  • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求

AJAX应用

最常见的是我们在百度输入东西时,百度只是局部刷新了一下即可,还有就是在网页注册登陆时,用到的也是这个原理,下面举个简单的登陆注册页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p>用户名<input type="text" name="username" onblur="func1(this)" onfocus="func2(this)">
    <span id="error"></span>
</p>
<p>密码<input type="password" name="password" onblur="func1(this)"><span id="pwd"></span></p>
<input type="submit" value="submit">


<script>

    function func1(self) {
        var username = self.value;
        var xmlhttp = creteXMLHttpRequest();

        xmlhttp.open("POST","/login/",true);
        xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

        xmlhttp.send("username="+username);

        xmlhttp.onreadystatechange=function() {
            if (xmlhttp.readyState == 4 && xmlhttp.status==200){
                 var data = xmlhttp.responseText;
                 if (data=="1"){
                     document.getElementById("error").innerHTML="该用户已经存在";
                     document.getElementById("pwd").innerHTML="密码不符合朴准"
                 }

            }
        };
    }

    function func2(self) {
        document.getElementById("error").innerHTML=""
    }

    function creteXMLHttpRequest() {
        var xmlHttp;
        xmlHttp = new XMLHttpRequest();
        return xmlHttp

    }
</script>


</body>
</html>
login.html
def login(req):

    if req.method == "POST":

        username = req.POST.get("username")

        if username == "flash":
            return HttpResponse('1')

        return HttpResponse('0')

    return render(req, "login.html")
login

AJAX的优缺点

优点

  • AJAX使用JavaScript技术向服务器发送异步请求。
  • AJAX无需刷新整个页面。
  • 因为服务器响应内容不再是整个页面,而是页面的局部,所以AJAX的性能高。

缺点

  • AJAX并不适合所有场景,很得时候还是要使用同步交互。
  • AJAX虽然提高了用户体验,但无形中向服务器发送的请求次数太多了,导致了服务器压力增大。
  • 因为AJAX是在浏览器中使用JavaScript技术完成的,所以还要处理浏览器的兼容问题。

AJAX技术

主要可以概括为四部操作

  • 创建核心对象;
  • 使用核心对象打开与服务器的连接;
  • 发送请求
  • 注册监听,监听服务器响应

XMLHTTPRequest对象

所有现代浏览器均支持XMLHTTPRequest对象(IE5和IE6使用 ActiveXObject)。

XMLHTTPRequest用于在后台与服务器交换数据。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

  • open(请求方式, URL, 是否异步)
  • send(请求体)
  • onreadystatechange,指定监听函数,它会在xmlHttp对象的状态发生变化时被调用

内容信息

  • readyState,当前xmlHttp对象的状态,其中4状态表示服务器响应结束
  • status:服务器响应的状态码,只有服务器响应结束时才有这个东东,200表示响应成功;
  • responseText:获取服务器的响应体

如果我们在创建对象时要考虑IE5和IE6的兼容性时,我们只需要,如果不需要,则不用写。

function createXMLHttpRequest() {
        var xmlHttp;
        // 适用于大多数浏览器,以及IE7和IE更高版本
        try{
            xmlHttp = new XMLHttpRequest();
        } catch (e) {
            // 适用于IE6
            try {
                xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                // 适用于IE5.5,以及IE更早版本
                try{
                    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e){}
            }
        }            
        return xmlHttp;
    }

AJAX-向服务器发送请求  

我们可以使用XMLHttpRequest对象的open()方法和send()方法。

open(method,url,async):规定请求类型,URL以及是否异步处理请求

  • menthod:请求的类型:GET或POST
  • url:文件在服务器上的位置
  • async: true(异步)或 flash(同步)。默认为true

send(string):将请求发送服务器请求

  • string:仅用于POST

当在下面情况下时,要使用POST请求

  • 无法使用缓存文件(更新服务器上的文件或数据库)
  • 向服务器发送大量数据(POST没有数据量限制)
  • 发送包含未知字符用户输入时,POST比GET更稳定也更可靠

当我们使用POST请求时,需要注意的是在open和send之间添加如下信息即可

xmlhttp.open("POST","ajax_test.asp",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("fname=Bill&lname=Gates");

服务器响应  

XMLHttpRequest对象有一个onreadystatechange事件,它会在XMLHttpRequest对象的状态发生变化时被调用。下面介绍一下XMLHttpRequest对象的5种状态:

  • 0:初始化未完成状态,只是创建了XMLHttpRequest对象,还未调用open()方法;
  • 1:请求已开始,open()方法已调用,但还没调用send()方法;
  • 2:请求发送完成状态,send()方法已调用;
  • 3:开始读取服务器响应;
  • 4:读取服务器响应结束。 

onreadystatechange事件会在状态为1234时引发。但通常我们只关心最后一种状态,即读取服务器响应结束时,客户端才会做出改变。我们可以通过XMLHttpRequest对象的readyState属性来得到XMLHttpRequest对象的状态。

xmlHttp.onreadystatechange = function() {
            if(xmlHttp.readyState == 4) {
                alert('hello');    
            }
        };

我们还需要考虑服务器响应的状态码是否为200等,可以用status获取状态妈如下

xmlHttp.onreadystatechange = function() {
            if(xmlHttp.readyState == 4 && xmlHttp.status == 200) {
                alert(xmlHttp.responseText);    
            }
        };

我们注意到了在获得来自服务器的响应时,可以使用responseText或responseXML属性来获取

  • responseText:获取字符串的响应数据
  • responseXML:获取XML形式的响应数据

jQuery实现AJAX

我们可以使用两个快捷方法去使用

$.get(url, [data], [callback], [type])
$.post(url, [data], [callback], [type])

下面以简单实例去看看如何显示。

def J_T(req):

    # print(req.GET) # 打印GET请求的数据
    # print(req.POST)  # 打印POST请求数据

    #dic = {"name": "aa"}

   # return HttpResponse(json.dumps(dic))
    return HttpResponse("OK")
<button id="b" onclick="func1()">点击</button>
<script>
    function func1() {
        test()
    }
    function test() {
      $.get('/J_T/');
      $.post('/J_T/')
    

  }

</script>
GET/POST
<script>
    function func1() {
        test()
    }
    function test() {
         $.get('/J_T/', function (data, callbacktype, jqXHR) {
         console.log(data); // OK
       console.log(callbacktype);//success
          console.log(jqXHR);  //object
   })
}


</script>
callback回调函数
<script>
    function func1() {
        test()
    }
    function test() {
          $.get('/J_T/?a=12&b=4')
          $.get('/J_T/',{a:12,b:4})
         $.post('/J_T/',{name:'aaa'})

}
</script>
传data

$.getScript()

$.getScript()使用 AJAX 请求,获取和运行 JavaScript:

function testGetScript() {
        // alert(testFun(3, 4));
        $.getScript('test.js', function () {
            alert(add(1, 6));
        });
    }

// test.js
function add(a,b){
   return a+b
   }

$.ajax的两种使用方式

function basicUsage() {
      //第一种
        $.ajax('/test', {
            success: function () {
                alert('ok');
            }
        });
    
     //第二种
        $.ajax({
            url: '/test',
            success: function () {
                alert('okk');
            }
        });
    }    

需要注意的事,success函数,在程序成功的时候会执行它,还有几种如下 success、error、statusCode、complete:

  • success:程序执行成功时促发的函数
  • error:程序执行失败时促发的函数
  • complete:不管程序成不成功都会促发的函数
  • statusCode:根据获取的状态码去对应的促发函数
function callbacksUsage() {
        $.ajax('/user/allusers', {

            success: function (data) {
                console.log(arguments);
                console.log("aa")
            },

            error: function (jqXHR, textStatus, err) {

                // jqXHR: jQuery增强的xhr
                // textStatus: 请求完成状态
                // err: 底层通过throw抛出的异常对象,类型与值与错误类型有关
                console.log(arguments);
            },

            complete: function (jqXHR, textStatus) {
                // jqXHR: jQuery增强的xhr
                // textStatus: 请求完成状态 success | error
                console.log('statusCode: %d, statusText: %s', jqXHR.status, jqXHR.statusText);
                console.log('textStatus: %s', textStatus);
            },

            statusCode: {
                '403': function (jqXHR, textStatus, err) {
                    console.log(arguments);
                    console.log('status code 403');
                    console.log("ahha403")
                },
                '400': function () {
                    console.log('status code 400');
                    console.log("hhhh400")
                }
            }
        });
    }
示例

在向服务器请求时的数据可分为4种: data, processData, contentType, traditional

  • data:当前ajax请求要携带的数据,是一个json的object对象,ajax方法就会默认地把它编码成某种格式(urlencoded:?a=1&b=2)发送给服务端;此外,ajax默认以get方式发送请求。
  • processData:声明当前的data数据是否进行转码或预处理,默认为true,即预处理;if 为false,那么对data:{a:1,b:2}会调用json对象的toString()方法,即{a:1,b:2}.toString(),最后得到一个[object,Object]形式的结果。一般情况下不做处理。
  • contentType:默认值: "application/x-www-form-urlencoded"。发送信息至服务器时内容编码类型。用来指明当前请求的数据编码格式;urlencoded: ?a=1&b=2;如果想以其他方式提交数据,比如contentType:"application/json",即向服务器发送一个json字符串:
  • traditional:一般是我们的data数据有数组时会用到

具体示例如下

function testData() {
       $.ajax("/test",{////此时的data是一个json形式的对象
          data:{
            a:1,
            b:2
          }      
       });

//显示结果  ?a=1&b=2
data
$.ajax({
          url:'/test/',
          type:"POST",
         data:{a:1,b:2},
          processData:false, //默认为true,改成false后不需要转码直接发送,不常用
        })
processData
$.ajax("/test",{
           
          data:JSON.stringify({
               a:22,
               b:33
           }),
           contentType:"application/json",
           type:"POST",
           
       });

//{a: 22, b: 33}
contentType

这里需要特别注意的是:contentType:"application/json"一旦设定,data必须是json字符串,不能是json对象

$.ajax({
        url:'/test/',
        type:"POST",
        data:{a:1,b:[3,4]}, //没加traditional之前{'b[]': ['3', '4'], 'a': ['1']}
        traditional:true  //加traditional之后 {'a': ['1'], 'b': ['3', '4']}
        })
        
traditional

响应数据分为dataType、dataFilter:

 dataType:预期服务器返回的数据类型,服务器端返回的数据会根据这个值解析后,传递给回调函数。默认不需要显性指定这个属性,ajax会根据服务器返回的content Type来进行转换;比如我们的服务器响应的content Type为json格式,这时ajax方法就会对响应的内容进行一个json格式的转换,if转换成功,我们在success的回调函数里就会得到一个json格式的对象;转换失败就会触发error这个回调函数。如果我们明确地指定目标类型,就可以使用data Type。比如服务器响应(Response Headers)的content Type是json格式(json对象),但是我们希望得到的是一个json字符串,那就可以把dataType:text,这样ajax方法就不会把返回的数据进行json格式的转换。

可用值:html|xml|json|text|script

from django.shortcuts import render,HttpResponse
from django.views.decorators.csrf import csrf_exempt
# Create your views here.

import json

def login(request):

    return render(request,'Ajax.html')


def ajax_get(request):

    l=['aa','little aa']

    #return HttpResponse(l)
    return HttpResponse(json.dumps(l))

//---------------------------------------------------
    function testData() {

        $.ajax('ajax_get', {
           success: function (data) {
           console.log(typeof(data));
                                     },
           dataType:"json",
                            }
                       )}

注解:Response Headers的content Type为text/html,所以返回的是String;但如果我们想要一个json对象
    设定dataType:"json"即可,相当于告诉ajax方法把服务器返回的数据转成json对象发送到前端.结果为objec
示例

dataFilter:Function 给 Ajax返回的原始数据的进行预处理的函数

function testData() {

         $.ajax('ajax_get', {
           success: function (data) {
               console.log(data);
            },


            dataType: 'json',
            dataFilter: function(data, type) {
                console.log(data);//["aa", "little aa"]
                console.log(type);//json
                //var tmp =  JSON.parse(data);
                return tmp.length;//2
            }
        });}
示例

前置处理 beforeSend(XHR)

类型:Function 发送请求前可修改 XMLHttpRequest 对象的函数,如添加自定义 HTTP 头。XMLHttpRequest 对象是唯一的参数。这是一个 Ajax 事件。如果返回 false 可以取消本次 ajax 请求。

function testData() {
        $.ajax('ajax_get', {
         beforeSend: function (jqXHR, settings) {
                console.log(arguments);
                console.log('beforeSend');
                jqXHR.setRequestHeader('test', 'haha');
                jqXHR.testData = {a: 1, b: 2};
            },
            success: function (data) {
                console.log(data);
            },

            complete: function (xhr) {
                console.log(xhr);
                console.log(xhr.testData);
            },

        })};
示例

jsonp

类型:String

在一个 jsonp 请求中重写回调函数的名字。这个值用来替代在 "callback=?" 这种 GET 或 POST 请求中 URL 参数里的 "callback" 部分,比如 {jsonp:'onJsonPLoad'} 会导致将 "onJsonPLoad=?" 传给服务器。

jsonpCallback

类型:String

为 jsonp 请求指定一个回调函数名。这个值将用来取代 jQuery 自动生成的随机函数名。这主要用来让 jQuery 生成度独特的函数名,这样管理请求更容易,也能方便地提供回调函数和错误处理。你也可以在想让浏览器缓存 GET 请求的时候,指定这个回调函数名。

JSON

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。

JSON是用字符串来表示Javascript对象,例如可以在django中发送一个JSON格式的字符串给客户端JavascriptJavascript可以执行这个字符串,得到一个Javascript对象。json就是js对象的一种表现形式(字符串的形式)

JSON语法(使用双引号包含数据 "...")

  • 数据在名称/值对中
  • 数据由逗号分隔
  • 花括号保存对象(对象需要使用大括号括起来)
  • 方括号保存数组(数组使用中括号括起来)

JSON值

  • 数字  (整数或浮点数)
  • 字符串(在双引号中)
  • 逻辑值(true 或 false
  • 数组   (在方括号中)
  • 对象   (在花括号中)
  • null

 .parse()和.stringify() 

  • .parse()是从一个字符串中解析出json对象
  • .stringify()是从一个对象中解析出字符串
var str = '{"name":"aa","age":"23"}'

结果:
JSON.parse(str)

str["name"]:  aa
str["age"]: 23

var a = {a:1,b:2}

结果:

JSON.stringify(a)

"{"a":1,"b":2}"

跨域请求 

在执行跨域请求时,对方需给我们提供一个接口,否则无法完成

首先了解什么是同源策略?

览器有一个很重要的概念——同源策略(Same-Origin Policy)。所谓同源是指,域名,协议,端口相同。不同源的客户端脚本(javascript、ActionScript)在没明确授权的情况下,不能读写对方的资源。

jsonp的js实现

JSONP是JSON with Padding的略称。可以让网页从别的域名(网站)那获取资料,即跨域读取数据。

它是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。

 #---------------------------http://127.0.0.1:8001/login

 def login(request):
    print('hello ajax')
    return render(request,'index.html')


 #---------------------------返回用户的index.html

 <h1>发送JSONP数据</h1>

<script>
    function fun1(arg){
        alert("hello"+arg)
    }
</script>
<script src="http://127.0.0.1:8002/get_byjsonp/"></script>


#-----------------------------http://127.0.0.1:8002/get_byjsonp

def get_byjsonp(req):
    print('8002...')
    return HttpResponse('fun1("aaa")')
View Code

动态的去创建script标签

<script>
    function addScriptTag(src){
     var script = document.createElement('script');  //空标签
         script.setAttribute("type","text/javascript");
         script.src = src;
         document.body.appendChild(script);  //添加到body内
    }
    function fun1(arg){
        alert("hello"+arg)
    }

    window.onload=function(){
        addScriptTag("http://127.0.0.1:8002/get_byjsonp/")
    }
</script>
创建script标签

将自己在客户端定义的回调函数的函数名传送给服务端,服务端则会返回以你定义的回调函数名的方法,将获取的json数据传入这个方法完成回调

<script>
    function addScriptTag(src){
     var script = document.createElement('script');
         script.setAttribute("type","text/javascript");
         script.src = src;
         document.body.appendChild(script);
    }
    function fetch(arg){
        alert("hello"+arg)
    }

    window.onload=function(){
        addScriptTag("http://127.0.0.1:8002/get_byjsonp?callback=fetch")
    }
    
</script>

#--------------------------------http://127.0.0.1:8002/get_byjsonp    
    def get_byjsonp(req):

    callback=req.GET.get('callback')
    print(callback)
    return HttpResponse('%s("aa")'%callback)
动态去取函数去执行

jQuery对JSONP的实现

jQuery使用时的方法为$.getJSON(url,[data],[callback])

<script type="text/javascript">
    $.getJSON("http://127.0.0.1:8002/get_byjsonp?callback=?",function(arg){
        alert("hello"+arg)
    });
</script>
<script type="text/javascript" src="/static/jquery-2.2.3.js"></script>

<script type="text/javascript">
   $.ajax({
        url:"http://127.0.0.1:8002/get_byjsonp",
        dataType:"jsonp",
        jsonp: 'callbacks',
        jsonpCallback:"fetch"
   });
    function fetch(arg){
        alert(arg);
    }
</script>
 
#--------------------------------- http://127.0.0.1:8002/get_byjsonp
 def get_byjsonp(req):

    callback=req.GET.get('callbacks')
    print(callback)
    return HttpResponse('%s("yuan")'%callback)
示例

我们也可不用去自己定义

<script type="text/javascript" src="/static/jquery-2.2.3.js"></script>

<script type="text/javascript">
   $.ajax({
        url:"http://127.0.0.1:8002/get_byjsonp",
        dataType:"jsonp",
        jsonp: 'callbacks',
        success:function(data){
            alert(data)
        }
   });

</script>
 #-------------------------------------http://127.0.0.1:8002/get_byjsonp
def get_byjsonp(req):

    callback=req.GET.get('callbacks')
    print(callback) #jQuery223015502220591490135_1477560648881
return HttpResponse("%s('aa')"%callback)
示例

需要注意的是:jsonpCallback:"fetch";如果不加这个参数,则自动生成一个随机名字。

下面我们利用跨域请求去请求一个电视台的列表信息

def index(req):

    return render(req, "index.html")
index函数
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<button onclick="func1()">AJAX提交</button>

<script src="/static/jquery-3.1.1.js"></script>

<script>
    function func1() {
        $.ajax({
            url:"http://www.jxntv.cn/data/jmd-jxtv2.html",
            type:"GET",
            dataType:"jsonp",
        })
    }

    //这里lsit函数被后台定死了,所以在$.ajax内部也就不用写jsonp: 'callbacks'和jsonpCallback:"fetch"了
    function list(e) {
        var obj=e['data'];
        $.each(obj,function () {  //循环遍历,相当于for循环
            console.log($(this));
            var weekend=$(this)[0]["week"];
            $("body").append("<p>"+weekend+"</p>");

            var show_list=$(this)[0]["list"];
            $.each(show_list,function () {
                var name=$(this)[0]["name"];
                var link=$(this)[0]["link"];
                $("body").append("<p><a href='"  +link  +    "'>" + name+"</a></p>")
            })

        })

    }

</script>

</body>

</html>
index.html

 

  

  

 

 

posted @ 2016-12-14 17:51  Dwyane.wang  阅读(215)  评论(0编辑  收藏  举报