Python全棧之路-Django(十六)

今日內容:Ajax
http://www.cnblogs.com/wupeiqi/articles/5703697.htmljavascript

1 Ajax介紹

AJAX,Asynchronous JavaScript and XML (異步的JavaScript和XML),一種建立交互式網頁應用的網頁開發技術方案。html

1.1異步的JavaScript:

使用 【JavaScript語言】 以及 相關【瀏覽器提供類庫】 的功能向服務端發送請求,當服務端處理完請求以後,【自動執行某個JavaScript的回調函數】。java

PS:以上請求和響應的整個過程是【偷偷】進行的,頁面上無任何感知。jquery

1.2 XML

XML是一種標記語言,是Ajax在和後臺交互時傳輸數據的格式之一
利用AJAX能夠作:ajax

  • 註冊時,輸入用戶名自動檢測用戶是否已經存在。
  • 登錄時,提示用戶名密碼錯誤
  • 刪除數據行時,將行ID發送到後臺,後臺在數據庫中刪除,數據庫刪除成功後,在頁面DOM中將數據行也刪除。

1.3 Ajax定義總結

偷偷向後臺發請求

2 Ajax發送數據

  • 原生Ajax,利用XMLHttpRequest對象
  • JQuery Ajax,內部基於原生Ajax
  • 僞Ajax,非XMLHttpRequest

2.1 原生Ajax

一、XmlHttpRequest對象介紹
XmlHttpRequest對象的主要方法:數據庫

a. void open(String method,String url,Boolen async)
   用於建立請求
    
   參數:
       method: 請求方式(字符串類型),如:POST、GET、DELETE...
       url:    要請求的地址(字符串類型)
       async:  是否異步(布爾類型)
 
b. void send(String body)
    用於發送請求
 
    參數:
        body: 要發送的數據(字符串類型)
 
c. void setRequestHeader(String header,String value)
    用於設置請求頭
 
    參數:
        header: 請求頭的key(字符串類型)
        vlaue:  請求頭的value(字符串類型)
 
d. String getAllResponseHeaders()
    獲取全部響應頭
 
    返回值:
        響應頭數據(字符串類型)
 
e. String getResponseHeader(String header)
    獲取響應頭中指定header的值
 
    參數:
        header: 響應頭的key(字符串類型)
 
    返回值:
        響應頭中指定的header對應的值
 
f. void abort()
 
    終止請求

XmlHttpRequest對象的主要屬性:json

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...

實例:跨域

a. XMLHttpRequest瀏覽器

GET請求:服務器

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
        alert(xhr.responseText);
    }
};
xhr.open('GET','/add2/?i1=12&i2=19');
xhr.send();

POST請求:

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
        alert(xhr.responseText);
    }
};
xhr.open('POST','/add2/');
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send("i1=12&i2=19");

2.2 僞Ajax

僞Ajax,非XMLHttpRequest,利用iframe標籤 不刷新打開頁面發送HTTP請求

app01.views.py

def fake_ajax(request):
    if request.method == 'GET':
        return render(request, 'fake_ajax.html')
    else:
        print(request.POST)
        return HttpResponse('...')

templates.fake_ajax.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form id="f1" action="/fake_ajax/" method="post" target="ifr" >
    <iframe id="ifr" frameborder="1" name="ifr" style="display: none;"></iframe>
    <input type="text" name="user">
    <input type="button" value="提交" onclick="submitForm();">
</form>
<script>
    function submitForm() {
        document.getElementById('f1').submit();
        document.getElementById('ifr').onload = LoadIframe;

    }
    function LoadIframe() {
        var content = document.getElementById('ifr').contentWindow.document.body.innerText
        alert(content)
    }
</script>
</body>
</html>

2.3 實例

templates.index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>首頁</h1>
    <input type="text" id="i1">
    +
    <input type="text" id="i2">
    =
    <input type="text" id="i3">

    <input type="button" id="btn1" value="JQuery Ajax" onclick="add1();">
    <input type="button" id="btn2" value="原生 Ajax" onclick="add2();">
    <script src="/static/jquery-3.2.1.min.js"></script>
    <script>
        function add1() {
            $.ajax({
                url: '/add1/',
                type: 'POST',
                data: {'i1': $('#i1').val(),'i2':$('#i2').val()},
                success: function (arg) {
                    $('#i3').val(arg)
                }
            })
        }
        function add2() {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
               if (xhr.readyState ==4){
                   alert(xhr.responseText);
               }
            };
            // xhr.open('GET','/add2/?i1=12&i2=19');
            xhr.open('POST','/add2/');
            xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
            xhr.send('i1=12&i2=19');
        }
    </script>
</body>
</html>

app01.views.py

def add1(request):
    i1 = int(request.POST.get('i1'))
    i2 = int(request.POST.get('i2'))
    return HttpResponse(i1+i2)


def add2(request):
    if request.method == 'GET':
        i1 = int(request.GET.get('i1'))
        i2 = int(request.GET.get('i2'))
        print(i1+i2)
        return HttpResponse(i1+i2)
    else:
        # i1 = int(request.POST.get('i1'))
        # i2 = int(request.POST.get('i2'))
        # print(i1 + i2)
        print(request.POST)
        print(request.body)
        return HttpResponse('...')

3 上傳文件

  • 基於原生Ajax XMLHttpRequest對象
  • JQuery Ajax
  • 僞Ajax

app01.views.py

import os
def upload(request):
    if request.method == 'GET':
        return render(request, 'upload.html')
    else:
        print(request.POST, request.FILES)
        file_obj = request.FILES.get('fafafa')
        file_path = os.path.join('static', file_obj.name)
        print(file_path)
        with open(file_path, 'wb') as f:
            for chunk in file_obj.chunks():
                f.write(chunk)
        return HttpResponse(file_path)

templates.upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>原生Ajax上傳文件</h1>
    <input type="file" id="i1">
    <a onclick="upload1();">上傳文件</a>
    <div id="container1"></div>

    <h1>JQuery Ajax上傳文件</h1>
    <input type="file" id="i2">
    <a onclick="upload2();">JQuery Ajax上傳文件</a>
    <div id="container2"></div>

    <h1>僞Ajax上傳文件</h1>
    <form id="f1" action="/upload/" method="post" target="ifr" enctype="multipart/form-data">
        <iframe id="ifr" name="ifr" style="display: none;"></iframe>
        <input type="file" id="i3" name="fafafa">
        <a onclick="upload3();">僞Ajax上傳文件</a>
    </form>
    <div id="container3"></div>

    <script src="/static/jquery-3.2.1.min.js"></script>
    <script>
        function upload1() {
            var formData = new FormData();
            formData.append('k1', 'v1');
            formData.append('fafafa', document.getElementById('i1').files[0]);
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4){
                    var  file_path = xhr.responseText;
                    var tag = document.createElement('img');
                    tag.src = "/"+ file_path;
                    document.getElementById('container1').appendChild(tag);

                }
            };
            xhr.open('POST','/upload/');
            // xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
            xhr.send(formData);
        }
        function upload2() {
            var formData = new FormData();
            formData.append('k1', 'v1');
            formData.append('fafafa', $('#i2')[0].files[0]);

            // DOM對象和JQuery對象的互換
            // $('#i2') -> $('#i2')[0]
            // document.getElementById('i1') -> $(document.getElementById('i1'))
            $.ajax({
                url: '/upload/',
                type: 'POST',
                data: formData,
                processData: false,  // 讓原生的FormData作處理
                contentType: false,  // 讓原生的FormData作處理
                success:function (arg) {
                    var tag = document.createElement('img');
                    tag.src = "/"+ arg;
                    $('#container2').append(tag)
                }
            })
            
        }
        function  upload3() {
            document.getElementById('ifr').onload = loadIframe;
            document.getElementById('f1').submit();
        }
        function loadIframe() {
            var content = document.getElementById('ifr').contentWindow.document.body.innerText;
            var tag = document.createElement('img');
            tag.src = "/"+ content;
            $('#container3').append(tag)
        }
    </script>
</body>
</html>

總結:

僞Ajax兼容性更好(建議上傳文件時使用),數據傳輸時建議使用JQuery

4 JSONP技術

4.1 Ajax存在的問題

  • 訪問其餘域名的URL會被阻止
  • 瀏覽器:
    • 同源策略,Ajax跨域發送請求時,再回來時瀏覽器拒絕接受
    • 容許script標籤

4.2 JSONP的本質

templates.jsonp.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="/static/commons.js"></script>
</head>
<body>
<a onclick="sendMsg();">發送</a>

<script src="/static/jquery-3.2.1.min.js"></script>
<script>
    function sendMsg() {
        // ajax會存在跨域問題
        /*
        $.ajax({
            url: 'http://dig.chouti.com/',
            type: 'GET',
            success:function (arg) {
                console.log(arg)
            }
        })
        */
        // 報錯:XMLHttpRequest cannot load http://dig.chouti.com/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8001' is therefore not allowed access.
        
        // JSONP
        var tag = document.createElement('script');
        tag.src = 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403';  // 返回list(數據)
        document.head.appendChild(tag); 
    }
</script>

</body>
</html>

/static/commons.js

function list(arg) {
    console.log(arg);
}
相關文章
相關標籤/搜索