zoukankan      html  css  js  c++  java
  • 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示例:

    ajax_demo.html

    复制代码

    <!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>
    复制代码
     
     
    views.py
    复制代码
    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)
    复制代码
    urls.py

    复制代码

    url(r"^ajax_demo/$", views.ajax_demo),
    url(r"^ajax_add/$", views.ajax_add),
    复制代码
    
    

    三、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"
  • 相关阅读:
    SCI写作经典替换词,瞬间高大上!(转)
    最佳化常用测试函数 Optimization Test functions
    算法复杂度速查表
    VS 代码行统计
    CPLEX IDE 菜单栏语言设置( 中文 英文 韩文 等多国语言 设置)
    如何从PDF文件中提取矢量图
    Matlab无法打开M文件的错误( Undefined function or method 'uiopen' for input arguments of type 'char)
    visual studio 资源视图 空白 解决方案
    MFC DialogBar 按钮灰色不响应
    嗨翻C语言笔记(二)
  • 原文地址:https://www.cnblogs.com/onesea/p/13158048.html
Copyright © 2011-2022 走看看