06: AJAX全套 & jsonp跨域AJAX

目錄:

1.1 AJAX介紹     返回頂部

  一、AJAX做用javascript

      1. AJAX 是一種在無需從新加載整個網頁的狀況下,可以更新部分網頁的技術。html

      2. AJAX = Asynchronous JavaScript and XML(異步的 JavaScript 和 XML)。java

      3. AJAX 不是新的編程語言,而是一種使用現有標準的新方法。jquery

  二、AJAX與傳統開發模式區別web

      ajax開發模式:頁面將用戶的操做經過ajax引擎與服務器進行通訊,將返回的結果給ajax引擎,而後ajax將數據插入指定位置。ajax

      傳統的開發模式:用戶的每一次操做都觸發一次返回服務器的HTTP請求,服務器作出處理後,返回一個html頁面給用戶。django

  三、AJAX請求的三種方法編程

      1. jQuery Ajax:本質 XMLHttpRequest 或 ActiveXObjectjson

      2. 原生Ajax:主要就是使用 【XmlHttpRequest】對象來完成請求的操做,該對象在主流瀏覽器中均存在跨域

      3. 「僞」AJAX:因爲HTML標籤的iframe標籤具備局部加載內容的特性,因此可使用其來僞造Ajax請求

1.2 jQuery AJAX(第一種)     返回頂部

  一、JQuery AJAX說明

                  一、jQuery其實就是一個JavaScript的類庫,其將複雜的功能作了上層封裝,使得開發者能夠在其基礎上寫更少的代碼實現更多的功能

                  二、jQuery Ajax本質 XMLHttpRequest 或 ActiveXObject

  二、使用JQuery AJAX發送數據

from django.shortcuts import render,HttpResponse
import json

def login(request):
    if request.method == 'GET':
        return render(request,'login.html')
    elif request.method == 'POST':
        print(request.POST)                    #{'name': ['root'], 'pwd': ['123']}
        ret = {'code':True,'data':None}
        return HttpResponse(json.dumps(ret))
views.py視圖函數
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form id="add_form">
        <input type="text" name="user" placeholder="用戶名">
        <input type="text" name="pwd" placeholder="密碼">
        <span id="jquery_ajax">JQuery Ajax提交</span>
    </form>
    <script src="/static/jquery-1.12.4.js"></script>
    
    <script>
        $('#jquery_ajax').click(function(){
            $.ajax({
                
                url: '/login/',
                // data: {'user': 123,'host_list': [1,2,3,4]},   // 也能夠這樣穿數據給後臺
                data: $('#add_form').serialize(),                //拿到form表單提交的全部內容
                type: "POST",
                dataType: 'JSON',                                // 讓JQuery將data先JSON後再發送到後臺
                traditional: true,                               //若是發送的是列表告訴JQuery也發送到後臺
                
                success: function(data, statusText, xmlHttpRequest){
                    if(data.code == true){
                        console.log('返回登陸後的頁面');
                    }else {
                        console.log('在頁面上添加錯誤提示信息');
                    }
                },
                
                error: function () {
                    //只有當發送數據,後臺沒有捕捉到的未知錯誤才執行error函數
                }
            })
        });
    </script>
</body>
</html>
login.html

    三、JQuery ajax藉助FormData上傳文件(藉助FormData低版本ie不支持)

from django.shortcuts import render,HttpResponse
import json

def upload(request):
    return render(request,'upload.html')

def upload_file(request):
    username = request.POST.get('username')
    fafafa = request.FILES.get('fafafa')
    print(username,fafafa)

    with open(fafafa.name,'wb') as f:
        for item in fafafa.chunks():
            f.write(item)
    ret = {'code':True,'data':request.POST.get('username')}
    return HttpResponse(json.dumps(ret))
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .upload{
            display: inline-block;
            padding: 10px;
            background-color: brown;
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            z-index: 90;
        }
        .file{
            width: 60px;
            height: 30px;
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            z-index: 100;
            opacity: 0;
        }
    </style>
</head>
<body>
    {# 爲了讓咱們的上傳圖標好看,能夠用咱們的a標籤顯示到上傳標籤的外面 #}
    <div style="position: relative;width: 60px;height: 40px">
        <input class="file" type="file" id="fafafa" name="afafaf">
        <a class="upload">上傳</a>
    </div>
    <input type="button" value="提交jQuery" onclick="fqSubmit();">

    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        function fqSubmit(){
            var file_obj = document.getElementById('fafafa').files[0];

            var fd = new FormData();            // FormData對象能夠傳字符串,也能夠傳文件對象
            fd.append('username','root');
            fd.append('fafafa',file_obj);
            var xhr = new XMLHttpRequest();

            $.ajax({
                url:'/upload_file/',
                type:'POST',
                data:fd,

                //jquery Ajax上傳文件必須執定processData,contentType參數
                processData:false,              //告訴JQuery不要特殊處理這個數據
                contentType:false,              //告訴JQuery不要設置內容格式
                success:function(arg,a1,a2){
                    console.log(111,arg);       //後臺返回的數據
                    console.log(222,a1);        //執行狀態:sucess(fail)
                    console.log(333,a2);        //對象
                }
            })
        }
    </script>
</body>
</html>
upload.html

  四、當框架加載完成發送ajax發送請求獲取數據

        // 當框架加載完成後執行此函數
        window.onload = function(){
            var deptid = $('[name="approvetype"]').val();
           $.ajax({
                url: '{% url "workordermanager:parse_deptid" %}',
                data: {'deptid': deptid},   // 也能夠這樣穿數據給後臺
                type: "get",
                dataType: 'JSON',                                // 讓JQuery將data先JSON後再發送到後臺
                traditional: true,                               //若是發送的是列表告訴JQuery也發送到後臺
                success: function(data, statusText, xmlHttpRequest){
                    if(data.code == true){
                        $('[name="approvetype"]').val(data.data);
                    }else {
                        console.log('在頁面上添加錯誤提示信息');
                    }
                },
                error: function () {
                    //只有當發送數據,後臺沒有捕捉到的未知錯誤才執行error函數
                }
            })
        }
當框架加載完成發送ajax獲取數據填充頁面

1.3 原生ajax(第二種)     返回頂部

  一、原生AJAX說明

      1. 原生Ajax主要就是使用 【XmlHttpRequest】對象來完成請求的操做

      2. 該對象在主流瀏覽器中均存在(除早起的IE),Ajax首次出現IE5.5中存在(ActiveX控件)

  二、XmlHttpRequest對象方法和屬性

// 一、void open(String method,String url,Boolen async)
    1)做用:用於建立請求
    2)參數:
        method: 請求方式(字符串類型),如:POST、GET、DELETE...
        url:    要請求的地址(字符串類型)
        async:  是否異步(布爾類型)
        
// 二、void send(String body)
    1)做用:用於發送請求
    2)參數:
            body: 要發送的數據(字符串類型)
            
// 三、void setRequestHeader(String header,String value)
    1)做用:用於設置請求頭
    2)參數:
        header: 請求頭的key(字符串類型)
        vlaue:  請求頭的value(字符串類型)
        
// 四、String getAllResponseHeaders()
    1)做用:獲取全部響應頭
    2)返回值:
        響應頭數據(字符串類型)
        
// 五、String getResponseHeader(String header)
    1)做用:獲取響應頭中指定header的值
    2)參數:
        header: 響應頭的key(字符串類型)
    3)返回值:  響應頭中指定的header對應的值
    
// 六、oid abort()
    1)做用:
        終止請求
XmlHttpRequest對象的主要方法
//a. Number readyState
   狀態值(整數)
 
   詳細:
      0-未初始化,還沒有調用open()方法;
      1-啓動,調用了open()方法,未調用send()方法;
      2-發送,已經調用了send()方法,未接收到響應;
      3-接收,已經接收到部分響應數據;
      4-完成,已經接收到所有響應數據;
 
//b. Function onreadystatechange
   當readyState的值改變時自動觸發執行其對應的函數(回調函數)
 
//c. String responseText
   服務器返回的數據(字符串類型)
 
//d. XmlDocument responseXML
   服務器返回的數據(Xml對象)
 
//e. Number states
   狀態碼(整數),如:200、404...
 
//f. String statesText
   狀態文本(字符串),如:OK、NotFound...
XmlHttpRequest對象的主要屬性

   三、使用原生AJAX發送數據(send方法發送)

from django.shortcuts import render,HttpResponse
import json

def login(request):
    if request.method == 'GET':
        return render(request,'login.html')
    elif request.method == 'POST':
        print(request.POST)                    #{'name': ['root'], 'pwd': ['123']}
        ret = {'code':True,'data':None}
        return HttpResponse(json.dumps(ret))
views.py視圖函數
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <input type="button" value="ajax1" onclick="Ajax1()">

    <script>
        // 使用原生ajax發送數據
        function Ajax1(){
            // var xhr = GetXHR();                              //(瀏覽器兼容性能夠這樣建立xhr對象)

            //1 new關鍵字建立JavaScript的XMLHttpRequest對象xhr
            var xhr = new XMLHttpRequest();                     //建立xhr對象(瀏覽器兼容性)

            //2 以get方式發數據給ajax_json,true表示支持異步
            xhr.open('POST','/login/',true);                    //open就是xhr對象的方法

            //3 onreadystatechange是:回調函數,當readyState的值改變時自動觸發執行其對應的匿名函數
            xhr.onreadystatechange = function(){
              if(xhr.readyState == '4'){                         // 只有狀態爲4時才執行 表示已經接收完畢
                  var obj = JSON.parse(xhr.responseText);       // xhr.responseText就是服務器端的返回值
                  console.log(obj);                              //獲取返回值:{code: true, data: null}
              }
            };

            //4 發送請求頭 CSRF中用的就是這個
            xhr.setRequestHeader('k1','v1');

            //5 後臺要想得到xhr.send數據,必須在這裏設置請求頭
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');

            //6 發送的字符串內容
            xhr.send("name=root;pwd=123");
        }


        // 原生ajax兼容ie低版本才使用這個方法建立XMLHttpRequest對象
        function GetXHR(){
            var xhr = null;                   //先設置xhr對象爲null
            if(XMLHttpRequest){
                xhr = new XMLHttpRequest();   //若是有XMLHttpRequest就設置
            }else{
                xhr = new ActiveXObject("Microsoft.XMLHTTP"); //沒有就設置成微軟的
            }
            return xhr;
        }
    </script>
</body>
</html>
login.html

   四、原生ajax藉助FormData上傳文件(藉助FormData低版本ie不支持)

from django.shortcuts import render,HttpResponse
import json

def upload(request):
    return render(request,'upload.html')

def upload_file(request):
    username = request.POST.get('username')
    fafafa = request.FILES.get('fafafa')
    print(username,fafafa)

    with open(fafafa.name,'wb') as f:
        for item in fafafa.chunks():
            f.write(item)
    ret = {'code':True,'data':request.POST.get('username')}
    return HttpResponse(json.dumps(ret))
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .upload{
            display: inline-block;
            padding: 10px;
            background-color: brown;
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            z-index: 90;
        }
        .file{
            width: 60px;
            height: 30px;
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            z-index: 100;
            opacity: 0;
        }
    </style>
</head>
<body>
    {# 爲了讓咱們的上傳圖標好看,能夠用咱們的a標籤顯示到上傳標籤的外面  #}
    <div style="position: relative;width: 60px;height: 40px">
        <input class="file" type="file" id="fafafa" name="afafaf">
        <a class="upload">上傳</a>
    </div>

    <input type="button" value="提交XHR" onclick="xhrSubmit();">

    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        // 原生ajax上傳文件
        function xhrSubmit(){
            var file_obj = document.getElementById('fafafa').files[0];
            var fd = new FormData();                    // FormData對象能夠傳字符串,也能夠傳文件對象
            fd.append('username','root');
            fd.append('fafafa',file_obj);

            var xhr = new XMLHttpRequest();
            xhr.open('POST','/upload_file/',true);     //open就是xhr對象的方法
            xhr.onreadystatechange = function(){
              if(xhr.readyState == '4'){
                  var obj = JSON.parse(xhr.responseText);
                  console.log(obj);
              }
            };
            xhr.send(fd);
        }
    </script>
</body>
</html>
upload.html

1.4 iframe「僞」AJAX(第三種)     返回頂部

   一、說明 

      1. 因爲HTML標籤的iframe標籤具備局部加載內容的特性,因此可使用其來僞造Ajax請求。

   二、使用僞AJAX發送數據

from django.shortcuts import render,HttpResponse
import json

def login(request):
    if request.method == 'GET':
        return render(request,'login.html')
    elif request.method == 'POST':
        print(request.POST)                    #{'name': ['root'], 'pwd': ['123']}
        ret = {'code':True,'data':None}
        return HttpResponse(json.dumps(ret))
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{#1 target="ifm1 就讓form和iframe創建關係,表單就會經過iframe提交數據到後臺   #}
{#2 能夠給submit綁定一個事件,當點擊時才綁定iframeLoad事件 #}
    <form action="/login/" method="POST" target="ifm1">
        <iframe name="ifm1" id="ifm1" style="display: none"></iframe>

        <input type="text" name="username">
        <input type="text" name="email">
        <input type="submit" value="Form提交" onclick="submitForm();">
    </form>

    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        //1 使用iframe提交數據,後臺返回數據放到iframe中了,須要拿到數據
        //2 只有當點擊提"Form提交"纔會觸發綁定iframe 的load事件
        //3 只有當後臺返回數據後,纔會自動觸發iframe的load事件

        function submitForm(){
            $('#ifm1').load(function(){

                var text = $('#ifm1').contents().find('body').text();  // contents()中就能夠獲取到後臺返回給iframe的內容了
                var obj = JSON.parse(text);                             //將字符串轉換成json數據
                console.log(obj)
            })
        }
    </script>
</body>
</html>
login.html

   三、iframe僞ajax上傳圖片及預覽(能夠兼容全部瀏覽器)

from django.shortcuts import render,HttpResponse
import json
import os

def upload_file(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        fafafa = request.FILES.get('fafafa')
        img_path = os.path.join('static\image',fafafa.name)
        print(img_path)
        with open(img_path,'wb') as f:
            for item in fafafa.chunks():
                f.write(item)
        ret = {'code':True,'data':img_path}
        return HttpResponse(json.dumps(ret))
    return render(request,'upload_file.html')
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/upload_file/" method="POST" target="ifm1" enctype="multipart/form-data">
        <iframe name="ifm1" id="ifm1" style="display: none"></iframe>
        <input type="file" name="fafafa">
        <input type="submit" value="iframe提交" onclick="iframeForm();">
    </form>
    <div id="preview"></div>

    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        function iframeForm(){
            $('#ifm1').load(function(){
                var text = $('#ifm1').contents().find('body').text();
                var obj = JSON.parse(text);                      //將字符串轉換成json數據
                var imgTag = document.createElement('img');     //建立image標籤
                $('#preview').empty();
                imgTag.src='/'+obj.data;                        //上傳後圖片路徑

                $('#preview').append(imgTag);
            })
        }
    </script>
</body>
</html>
法1:upload.html不定義上傳按鈕樣式
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form id="fm" action="/upload_file/" method="POST" target="ifm1" enctype="multipart/form-data">
        <iframe name="ifm1" id="ifm1" style="display: none"></iframe>
        <input type="file" name="fafafa" onchange="iframeForm();" id="publish_file" style="display: none">
        <a onclick="document.getElementById('publish_file').click();">上傳圖片</a>
    </form>
    <div id="preview"></div>

    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        function iframeForm(){
            $('#ifm1').load(function(){
                var text = $('#ifm1').contents().find('body').text();
                var obj = JSON.parse(text);                      //將字符串轉換成json數據
                var imgTag = document.createElement('img');     //建立image標籤
                $('#preview').empty();
                imgTag.src='/'+obj.data;                        //上傳後圖片路徑

                $('#preview').append(imgTag);
            });
            
            document.getElementById('fm').submit();
        }
    </script>
</body>
</html>
法2:upload.html自定義上傳按鈕樣式

1.5 jsonp跨域請求     返回頂部

   一、jsonp跨域請求原理

      1. 因爲瀏覽器存在同源策略機制,同源策略阻止經過js經過瀏覽器設置另外一個源加載的文檔的屬性。

      2. 好比如今訪問 http://127.0.01/index 頁面,在index頁面中經過js發送請求獲取 http://tom.com/login/ 頁面的數據會被瀏覽器阻止

      3. 因爲同源策略是瀏覽器的限制,因此請求的發送和響應是能夠進行,只不過瀏覽器不接受返回來的數據罷了

      4. 瀏覽器同源策略僅制約XmlHttpRequest,不會制約 img、iframe、script等具備src屬性的標籤

      5. JSONP(JSON with Padding是JSON的一種「使用模式」),利用script標籤的src屬性實現jsonp跨域請求

      6. JSONP實質就是經過scrip的src屬性向其餘域請求數據,這樣就能夠在網頁中獲取到遠端路徑的數據了

  二、實現jsonp跨域請求測試分爲如下幾步

      1. 首先須要創建第兩個Django項目MyNewDay25  和 anotherDomainProject

      2.從MyNewDay25 的Django項目經過AJAX,向  anotherDomainProject項目請求數據

      3.  這裏由於在同一臺計算機中測試,因此將anotherDomainProject 監聽端口改成8001

      4.  爲了實現不一樣域名的效果,修改計算機hosts記錄:

        路徑: C:\Windows\System32\drivers\etc\hosts

        添加: 127.0.0.1       tom.com

        目的:經過 http://tom.com:8001/another_domain_project/?callback=list'  訪問anotherDomainProject

   二、MyNewDay25  項目中發送請求給anotherDomainProject獲取數據

    1. MyNewDay25代碼

        說明:當咱們訪問MyNewDay25項目的: http://127.0.0.1:8000/get_data/    時就會使用ajax到

                 http://tom.com:8001/another_domain_project/ 獲取數據,而後經過console.log打印出來

from django.shortcuts import render,HttpResponse

def get_data(request):
    return render(request,'get_data.html')
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <input type="button" value="獲取數據" onclick="getContent();" />

    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        function getContent(){
            // 1. 使用原生js的src屬性跨域請求數據
            var tag = document.createElement('script');
            tag.src = 'http://tom.com:8001/another_domain_project/?callback=list';
            // tag.src = 'http://www.jxntv.cn/data/jmd-jxtv2.html?calback=list&_=1454376870403';
            document.head.appendChild(tag);
            document.head.removeChild(tag);

            // 2. 使用ajax實現jsonp跨域請求
            $.ajax({
                url: 'http://tom.com:8001/another_domain_project/',
                type: 'POST',
                dataType: 'jsonp',
                // 下面的兩句就至關於上面再URL中寫:?callback=list
                jsonp: 'callback',
                jsonpCallback: 'list'
            })
        }

        // 3.這個函數就是當數據返回後使用list函數處理:arg就是跨域請求來的數據
        function list(arg){
            console.log(arg);
        }
    </script>
</body>
</html>
get_data.html

    2. anotherDomainProject代碼

ALLOWED_HOSTS = ['tom.com','127.0.0.1',]
settings.py
from django.shortcuts import render,HttpResponse

def another_domain_project(request):       # 請求端發送AJAX請求路徑:http://tom.com:8001/another_domain_project/?callback=list
    func = request.GET.get('callback')    # 獲取請求端回調函數名(這裏名字是:list,字符串格式)
    content = '%s(1000000)'%(func)        # 返回給請求端內容:list(1000000), 在請求端就會調用js中的list()函數了
    return HttpResponse(content)
views.py

1.6 在tornado中使用jsonp解決跨域請求     返回頂部

import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.set_header('Access-Control-Allow-Origin', "")
        self.render('get_data.html')

settings = {
    'template_path': 'template',
    'static_path': 'static',
    'static_url_prefix': '/static/',
}

application = tornado.web.Application([
    (r"/get_date", MainHandler),
], **settings)

if __name__ == "__main__":
    application.listen(8000)
    print('http://127.0.0.1:8000/get_date')
    tornado.ioloop.IOLoop.instance().start()
app.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<input type="button" onclick="AjaxRequest()" value="跨域Ajax" />

<div id="container"></div>

<script src="/static/jquery-1.12.4.js" type="text/javascript"></script>
    <script type="text/javascript">
        function AjaxRequest() {
            $.ajax({      // 下面這個路徑是江西衛視界面菜單的json數據
                url: 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403',
                type: 'GET',
                dataType: 'jsonp',
                jsonp: 'callback',
                jsonpCallback: 'list',
                success: function (data) {
                    $.each(data.data,function(i){
                        var item = data.data[i];
                        var str = "<p>"+ item.week +"</p>";
                        $('#container').append(str);
                        $.each(item.list,function(j){
                            var temp = "<a href='" + item.list[j].link +"'>" + item.list[j].name +" </a><br/>";
                            $('#container').append(temp);
                        });
                        $('#container').append("<hr/>");
                    })
                }
            });
        }
</script>
</body>
</html>
get_data.html
相關文章
相關標籤/搜索