• Ajax


    一、准备知识

    什么是json?

    JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。
    它基于ECMAScript(w3c制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。
    简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

    合格的json对象:

    ["one", "two", "three"]
    {"one": 1, "two": 2, "three": 3}
    {"names": ["张三", "李四"] }
    [{ "name": "张三"}, {"name": "李四"}]

    不合格的json对象:

    { name: "张三", 'age': 32 }  # 属性名必须使用双引号
    [32, 64, 128, 0xFFF]  # 不能使用十六进制值
    { "name": "张三", "age": undefined }  # 不能使用undefined
    { "name": "张三",
      "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
      "getName":  function() {return this.name;}  # 不能使用函数和日期对象
    }

    stringify与parse方法

    JavaScript中关于JSON对象和字符串转换的两个方法:

    JSON.parse():用于将一个 JSON 字符串转换为 JavaScript 对象

    JSON.parse('{"name":"pd"}');
    JSON.parse('{name:"pd"}');  # 错误
    JSON.parse('[18,undefined]');  # 错误

    JSON.stringify():用于将 JavaScript 值转换为 JSON 字符串

    JSON.stringify({"name":"pd"})

    二、Ajax简介

    AJAX(Asynchronous Javascript And XML)翻译成中文就是"异步Javascript和XML"。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据)

    AJAX除了异步的特点外,还有一个就是:浏览器页面局部刷新;(这一特点给用户的感受就是在不知不觉中完成了请求和响应过程)

    优点:

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

    jQuery实现Ajax示例:

    <!DOCTYPE html>
    <html lang="zh-cn">
    <head>
        <meta charset="UTF-8">
        <title>ajax_demo</title>
        <script type="text/javascript" src="/static/jquery-3.3.1.min.js"></script>
    </head>
    <body>
    
    <input type="text" id="i1">+
    <input type="text" id="i2">=
    <input type="text" id="i3">
    <button type="button" id="btn">提交</button>
    
    <script>
        $("#btn").click(function () {
            var i1 = $("#i1").val();
            var i2 = $("#i2").val();
            $.ajax({
                url:"/ajax_add/",
                type: "GET",
                data: {"i1": i1, "i2": i2},
                success:function (ret) {
                    $("#i3").val(ret)
                }
            })
        })
    </script>
    </body>
    </html>
    ajax_demo.html
    def ajax_demo(request):
        return render(request, "ajax_demo.html")
    
    
    def ajax_add(request):
        i1 = request.GET.get("i1")
        i2 = request.GET.get("i2")
        ret = int(i1) + int(i2)
        return HttpResponse(ret)
    views.py
    url(r"^ajax_demo/$", views.ajax_demo),
    url(r"^ajax_add/$", views.ajax_add),
    urls.py

    三、jQuery实现Ajax

    <button class="send_Ajax">send_Ajax</button>
    
    <script>
        $(".send_Ajax").click(function () {
            $.ajax({
                url: "/test/",
                type: "POST",
                data: {username: "pd", password: 123},
    
                // -------- success --------
                success: function (data) {
                    alert(data)
                },
    
                // -------- error --------
                error: function (jqXHR, textStatus, err) {
                    // jqXHR: jQuery增强的xhr
                    // textStatus: 请求完成状态
                    // err: 底层通过throw抛出的异常对象,值与错误类型有关
                    console.log(arguments);
                },
    
                // -------- complete --------
                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 --------
                statusCode: {
                    "403": function (jqXHR, textStatus, err) {
                        console.log(arguments);  // 注意:后端模拟error方式:HttpResponse.status_code=500
                    },
                    "400": function () {
                    }
                }
            })
        })
    </script>

    data参数中的键值对,如果值不为字符串,则需要将其装换成字符串类型;如:"lst": JSON.stringify([1, 2, 3])

    $.ajax(...)
            url:请求地址
           type:请求方式,GET、POST(1.9.0之后用 method)
        headers:请求头
           data:要发送的数据
    contentType:即将发送信息至服务器的内容编码类型(默认: "application/x-www-form-urlencoded; charset=UTF-8")
          async:是否异步
        timeout:设置请求超时时间(毫秒)
    
     beforeSend:发送请求前执行的函数(全局)
       complete:完成之后执行的回调函数(全局)
        success:成功之后执行的回调函数(全局)
          error:失败之后执行的回调函数(全局)
        
        accepts:通过请求头发送给服务器,告诉服务器当前客户端课接受的数据类型
       dataType:将服务器端返回的数据转换成指定类型
               "xml": 将服务器端返回的内容转换成xml格式
              "text": 将服务器端返回的内容转换成普通文本格式
              "html": 将服务器端返回的内容转换成普通文本格式,在插入DOM中时,如果包含JavaScript标签,则会尝试去执行。
            "script": 尝试将返回值当作JavaScript去执行,然后再将服务器端返回的内容转换成普通文本格式
              "json": 将服务器端返回的内容转换成相应的JavaScript对象
             "jsonp": JSONP格式
     converters: 转换器,将服务器端的内容根据指定的dataType转换类型,并传值给success回调函数

    请求参数

    contentType:    默认为"application/x-www-form-urlencoded";代表发送信息至服务器时内容编码类型。
                     用来指明当前请求的数据编码格式;urlencoded:?a=1&b=2;
                     如果想以其他方式提交数据,比如contentType: "application/json",即向服务器发送一个json字符串:
                        <button class="send_Ajax">send_Ajax</button>
                        <script>
                            $(".send_Ajax").click(function () {
                                $.ajax({
                                    url: "/test/",
                                    type: "post",
                                    contentType: "application/json",
                                    data: JSON.stringify({a: 11, b: 22}),
                                    success:function (data) {
                                        alert(data)
                                    }
                                })
                            })
                        </script>
                     注意:contentType: "application/json"一旦设定,data必须是json字符串,不能是json对象。

    响应参数

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

    四、Ajax请求设置csrf_token

    通过获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送。

    <script>
        $("#btn").click(function () {
            var i1 = $("#i1").val();
            var i2 = $("#i2").val();
            $.ajax({
                url:"/ajax_add/",
                type: "POST",
                data: {"i1": i1, "i2": i2, "csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val()},
                success:function (ret) {
                    $("#i3").val(ret)
                }
            })
        })
    </script>

    五、Ajax上传文件

    XMLHttpRequest 是一个浏览器接口,通过它,我们可以使得 Javascript 进行 HTTP(S) 通信。XMLHttpRequest 在现在浏览器中是一种常用的前后台交互数据的方式。2008年 2 月,XMLHttpRequest Level 2 草案提出来了,相对于上一代,它有一些新的特性,其中 FormData 就是 XMLHttpRequest Level 2 新增的一个对象,利用它来提交表单、模拟表单提交,当然最大的优势就是可以上传二进制文件。下面就具体介绍一下如何利用 FormData 来上传文件。

    formData的基本用法:FormData对象,可以把所有表单元素的name与value组成一个queryString,提交到后台。只需要把 form 表单作为参数传入 FormData 构造函数即可:

    # 上传文件示例
    $("#b3").click(function () {
        var formData = new FormData();
        formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());
        formData.append("f1", $("#f1")[0].files[0]);
        $.ajax({
            url: "/upload/",
            type: "POST",
            processData: false,  # 告诉jQuery不要去处理发送的数据
            contentType: false,  # 告诉jQuery不要去设置Content-Type请求头
            data: formData,
            success:function (data) {
                console.log(data)
            }
        })
    })

    注意:由于 FormData 是 XMLHttpRequest Level 2 新增的接口,现在 低于IE10 的IE浏览器不支持 FormData。

    六、jQuery.serialize()

    serialize()函数用于序列化一组表单元素,将表单内容编码为用于提交的字符串。

    serialize()函数常用于将表单内容序列化,以便用于AJAX提交。

    该函数不会序列化不需要提交的表单控件,这和常规的表单提交行为是一致的。例如:不在<form>标签内的表单控件不会被提交、没有name属性的表单控件不会被提交、带有disabled属性的表单控件不会被提交、没有被选中的表单控件不会被提交。

    与常规表单提交不一样的是:常规表单一般会提交带有name的按钮控件,而serialize()函数不会序列化带有name的按钮控件。
    <form action="" id="id_form">
        {% csrf_token %}
        <p><input type="text" name="username" id="id_username" placeholder="账号"></p>
        <p><input type="password" name="password" id="id_password" placeholder="密码"></p>
        <p><button type="button" id="id_login">登录</button></p>
    </form>
    <script src="/static/jquery-3.3.1.min.js"></script>
    <script>
        $("#id_login").click(function () {
            $.ajax({
                url:"/ajax/",
                type: "post",
                data: $("#id_form").serialize(),
                dataType: "json",
                success:function (arg) {
                    if (arg=="1"){
                        location.href="http://www.sogo.com"
                    }else {
                        alert(arg)
                    }
                }
            })
        })
    </script>

    七、JSONP

    jsonp是json用来跨域的一个东西。原理是通过script标签的跨域特性来绕过同源策略。

    下面的示例为:jQuery对JSONP的实现

    假设项目 jsonp_test1 的某个页面向项目 jsonp_test2 的某个路径请求数据。

    jsonp_test1

    #jsonp_test1/urls.py
    
    from django.conf.urls import url
    from appxx import views
    
    urlpatterns = [
        url(r"^$", views.index)
    ]
    #jsonp_test1/views.py
    
    from django.shortcuts import render
    
    def index(request):
        return render(request, "index.html")
    #jsonp_test1/index.html
    
    <!DOCTYPE html>
    <html lang="zh-cn">
    <head>
        <meta charset="UTF-8">
        <title>INDEX</title>
        <script type="text/javascript" src="/static/js/jquery-3.3.1.min.js"></script>
    </head>
    <body>
    <h3>INDEX页面</h3>
    <button id="id_btn">跨域ajax</button>
    </body>
    <script>
        $("#id_btn").click(function () {
            $.ajax({
                url: "http://127.0.0.1:8888/jsonp_ajax/",   // 请求数据的路径
                type: "get",                // 注意jsonp一定是get请求
                dataType: "jsonp",          // 必须有,告诉server,这次访问要的是一个jsonp的结果
                jsonp: "callbacks",         // jQuery帮助随机生成的:callbacks="......"
                success:function (data) {
                    console.log(data)
                }
            })
        })
    </script>
    </html>

    jsonp_test2

    #jsonp_test2/urls.py
    
    from django.conf.urls import url
    from appxx import views
    
    urlpatterns = [
        url(r"^jsonp_ajax/", views.jsonp_ajax)
    ]
    #jsonp_test2/views.py
    
    from django.shortcuts import HttpResponse
    import json
    
    def jsonp_ajax(request):
        func = request.GET.get("callbacks")
        data = {"title": "python", "price": 100, "author": "pd"}
        return HttpResponse("{}({})".format(func, json.dumps(data)))

    jsonp实际应用示例

    <!DOCTYPE html>
    <html lang="zh-cn">
    <head>
        <meta charset="UTF-8">
        <title>INDEX</title>
        <script type="text/javascript" src="/static/js/jquery-3.3.1.min.js"></script>
    </head>
    <body>
    
    <h3>INDEX页面</h3>
    <button id="id_btn">跨域ajax</button>
    <div id="content"></div>
    
    </body>
    <script>
        $("#id_btn").click(function () {
            $.ajax({
                url: "http://www.jxntv.cn/data/jmd-jxtv2.html",
                type: "get",
                dataType: "jsonp",
                jsonp: "callbacks",
                jsonpCallback: 'list',
                success:function (data) {
                    console.log(data.data);
                    $.each(data.data, function (index1, items) {
                        var html = "";
                        html += '<h3>'+items.week+'</h3>';
                        $.each(items.list, function (index2, show) {
                            html += '<p><a href='+show.link+'>'+show.name+'</a></p>';
                        });
                        $("#content").append(html);
                    })
                }
            })
        })
    </script>
    </html>

    八、CORS

    #jsonp_test1/index.html
    
    <!DOCTYPE html>
    <html lang="zh-cn">
    <head>
        <meta charset="UTF-8">
        <title>INDEX</title>
        <script type="text/javascript" src="/static/js/jquery-3.3.1.min.js"></script>
    </head>
    <body>
    
    <h3>INDEX页面</h3>
    <button id="id_btn">跨域ajax</button>
    <div id="content"></div>
    
    </body>
    <script>
        $("#id_btn").click(function () {
            $.ajax({
                url: "http://127.0.0.1:8888/jsonp_ajax/",
                success:function (data) {
                     console.log(JSON.parse(data))
                 }
            })
        })
    </script>
    </html>
    #jsonp_test2/views.py
    
    from django.shortcuts import HttpResponse
    import json
    
    def jsonp_ajax(request):
        data = {"title": "python", "price": 100, "author": "pd"}
        response = HttpResponse(json.dumps(data))
        response["Access-Control-Allow-Origin"] = "http://127.0.0.1:8000"
        # response["Access-Control-Allow-Origin"] = "*"
        return response

    一、简介

    CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

    整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

    因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

    二、两种请求

    浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

    只要同时满足以下两大条件,就属于简单请求。

    (1) 请求方法是以下三种方法之一:
    HEAD
    GET
    POST
    (2)HTTP的头信息不超出以下几种字段:
    Accept
    Accept-Language
    Content-Language
    Last-Event-ID
    Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

    凡是不同时满足上面两个条件,就属于非简单请求。

    浏览器对这两种请求的处理,是不一样的。

    *简单请求和非简单请求的区别?
        简单请求:一次请求
        非简单请求:两次请求,在发送数据之前会先发一次请求用于做"预检",只有"预检"通过后才再发送一次请求用于数据传输。
    *关于“预检”
    
    -> 请求方式:OPTIONS
    -> "预检"其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
    -> 如何"预检"
        -> 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则"预检"不通过
           Access-Control-Request-Method
        -> 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则"预检"不通过
           Access-Control-Request-Headers

    支持跨域,简单请求

    服务器设置响应头:Access-Control-Allow-Origin = "域名" 或 "*"

    # 允许你的域名来获取我的数据
    response["Access-Control-Allow-Origin"] = "http://127.0.0.1:8080"

    支持跨域,复杂请求

    由于复杂请求时,首先会发送"预检"请求,如果"预检"成功,则发送真实数据。

    • "预检"请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
    # 允许你发送PUT、DELETE请求
    response["Access-Control-Request-Method"] = "PUT,DELETE"
    • "预检"请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers
    # 允许你携带Content-Type请求头
    response["Access-Control-Request-Headers"] = "Content-Type"
  • 相关阅读:
    VB.NET程序设计笔记
    ASP.NET动态的网页增删查改
    一般处理程序加简单三层实现增删查改(2)
    一般处理程序加简单三层实现增删查改(1)
    设计模式六大原则(1):单一职责原则
    Android Https相关完全解析 当OkHttp遇到Https
    Androrid应用打包release版时关闭log日志输出
    Fragment结合ViewPager之懒加载
    多线程基础
    Android Studio wifi调试
  • 原文地址:https://www.cnblogs.com/believepd/p/9920537.html
Copyright © 2020-2023  润新知