• AJAX全套 & jsonp跨域AJAX


    1.1 AJAX介绍

      1、AJAX作用

          1. AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。

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

          3. AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

      2、AJAX与传统开发模式区别

          ajax开发模式:页面将用户的操作通过ajax引擎与服务器进行通信,将返回的结果给ajax引擎,然后ajax将数据插入指定位置。

          传统的开发模式:用户的每一次操作都触发一次返回服务器的HTTP请求,服务器做出处理后,返回一个html页面给用户。

      3、AJAX请求的三种方法

          1. jQuery Ajax:本质 XMLHttpRequest 或 ActiveXObject

          2. 原生Ajax:主要就是使用 【XmlHttpRequest】对象来完成请求的操作,该对象在主流浏览器中均存在

          3. “伪”AJAX:由于HTML标签的iframe标签具有局部加载内容的特性,所以可以使用其来伪造Ajax请求

    1.2 jQuery AJAX(第一种)

      1、JQuery AJAX说明

                      1、jQuery其实就是一个JavaScript的类库,其将复杂的功能做了上层封装,使得开发者可以在其基础上写更少的代码实现更多的功能

                      2、jQuery Ajax本质 XMLHttpRequest 或 ActiveXObject

      2、使用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

        3、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; 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

      4、当框架加载完成发送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(第二种)

      1、原生AJAX说明

          1. 原生Ajax主要就是使用 【XmlHttpRequest】对象来完成请求的操作

          2. 该对象在主流浏览器中均存在(除早起的IE),Ajax首次出现IE5.5中存在(ActiveX控件)

      2、XmlHttpRequest对象方法和属性

    // 1、void open(String method,String url,Boolen async)
        1)作用:用于创建请求
        2)参数:
            method: 请求方式(字符串类型),如:POST、GET、DELETE...
            url:    要请求的地址(字符串类型)
            async:  是否异步(布尔类型)
            
    // 2、void send(String body)
        1)作用:用于发送请求
        2)参数:
                body: 要发送的数据(字符串类型)
                
    // 3、void setRequestHeader(String header,String value)
        1)作用:用于设置请求头
        2)参数:
            header: 请求头的key(字符串类型)
            vlaue:  请求头的value(字符串类型)
            
    // 4、String getAllResponseHeaders()
        1)作用:获取所有响应头
        2)返回值:
            响应头数据(字符串类型)
            
    // 5、String getResponseHeader(String header)
        1)作用:获取响应头中指定header的值
        2)参数:
            header: 响应头的key(字符串类型)
        3)返回值:  响应头中指定的header对应的值
        
    // 6、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对象的主要属性

       3、使用原生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

       4、原生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; 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、说明 

          1. 由于HTML标签的iframe标签具有局部加载内容的特性,所以可以使用其来伪造Ajax请求。

       2、使用伪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

       3、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('staticimage',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跨域请求

       1、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属性向其他域请求数据,这样就可以在网页中获取到远端路径的数据了

      2、实现jsonp跨域请求测试分为以下几步

          1. 首先需要建立第两个Django项目MyNewDay25  和 anotherDomainProject

          2.从MyNewDay25 的Django项目通过AJAX,向  anotherDomainProject项目请求数据

          3.  这里因为在同一台计算机中测试,所以将anotherDomainProject 监听端口改为8001

          4.  为了实现不同域名的效果,修改计算机hosts记录:

            路径: C:WindowsSystem32driversetchosts

            添加: 127.0.0.1       tom.com

            目的:通过 http://tom.com:8001/another_domain_project/?callback=list'  访问anotherDomainProject

       2、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
  • 相关阅读:
    SqlServer丢失.ldf日志文件,附加数据库mdf文件的解决办法
    NetCore+Consul服务注册+Ocelot网关配置
    docker 配置apollo
    docker部署nacos
    金蝶云星空自定义WebApi接口开发和调用
    挂载错误:系统不支持 cifs 文件系统
    staticmethod classmethod
    Kitex源码阅读——脚手架代码是如何通过命令行生成的(一)
    Kitex源码阅读——脚手架代码是如何通过命令行生成的(二)
    GO的日志库log竟然这么简单!
  • 原文地址:https://www.cnblogs.com/jiaxinzhu/p/12667251.html
Copyright © 2020-2023  润新知