ajax

向后台传输数据有两种方式1、form 提交后会刷新页面 2、ajax 提交数据后不会刷新页面

ajax是XMLHttPRequest对象。使用ajax分为3种情况,1、手动使用  2、jQuery方式使用  3、伪ajax

1、当遇到需求,不使用jQuery方式用ajax向后台发送数据。

<a href="#" onclick="func()">点击</a>
    function func() {
        var xhr = new XMLHttpRequest();//创建XMLHttpRequest对象
        xhr.onreadystatechange = function(){
            if(xhr.readyState == 4){
                console.log(xhr.responseText);//xhr.responseText保存着服务端返回来的信息
            }
        };//以XMLHttpRequest对象向后台发送数据执行的回调函数,某些状态更改会触发执行。
        //xhr.readyState取值有0-4
        xhr.open("GET", "/ajax_2?p=123");
        xhr.send(null);
    }
def ajax_2(request):
    print(request.POST)
    print(request.GET)
    return HttpResponse("ok")

后台没有对接收到的数据进行处理,只是打印接收到的数据。

上述代码的步骤为:1、创建 XMLHttpRequest对象,2、根据该对象设置回调函数,3、以什么方式,向哪个url创建连接,4、发送数据。回调函数中,xhr的状态改变就会触发回调函数的执行,其状态保存在xhr.readyState中,其详细的状态有

0——未初始化,尚未调用open方法

1——启动,调用了open()方法,还未调用send()方法。

2——发送,已经调用了send()方法,还未接收到响应。

3——接收,已经接收到部分响应数据。

4——完成,已经接收到全部响应数据。

发送get请求和post请求不一样,发送post请求需要设置发送的请求头。

request请求有请求头和请求体。数据发送是在request.body中,然后提取到request.GET;request.POST中,采用该方式发送数据时,请求头没有设置成Django能够识别的形式,因此需要将请求头设置成django能够识别的形式。

 

<a href="#" onclick="func_1()">点击</a>
    function func_1() {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function(){
            if(xhr.readyState == 4){
                console.log(xhr.responseText);
            }
        };
        xhr.open("POST", "/ajax_2/");
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8')//设置请求头,Django中固定这种设置,还可以进行其他
//的设置,这样设置Django能够解析
        xhr.send("p=456");
    }
def ajax_2(request):
    print(request.POST)
    print(request.GET)
    return HttpResponse("ok")

 2、伪ajax

方法:采用iframe标签和form表单一起合用完成向后台发送数据而又不刷新页面。

该方法是兼容性最好的一种方式。

认识iframe:iframe有默认高度和宽度,在页面上显示类似于文本框textarea,有src属性,通过src属性发送请求,请求发送到后台,后台处理后将处理结果返回显示到iframe自己的内容区域中,外面的大的页面不刷新。

因此配合使用时需要做两点:2、在form表单上加上target="iframe标签的那么属性值"1、在iframe标签上加上name="名字"

    <iframe name="ifra_a" onload="loadData(this)" id="ifra_2"></iframe>
    <form id="fm_a" action="/file_upload_1/" method="post" enctype="multipart/form-data" target="ifra_a">
        <input type="file" name="test_file3" id="input_c" onchange="func_4()">
    </form>

这样配合起来使用后,form提交到自己设定的路径的后台处理,后台处理后将处理的结果返回到iframe标签的内容区中。onchange表示输入框内容改变执行对应的函数。

回调函数,怎么取iframe标签中的值?

认识js中的this

1、在一个具体的标签中,this带指这一个标签。

在一个标签中有两种情况:1

 <iframe name="ifra_a" onload="loadData(this)" id="ifra_2"></iframe>

2:

    $("#ifra_2").click(function () {
        $(this).html();
    })

2、没有在一个具体的标签中,this带指window对象。

func_4()实现提交form表单,相当于input标签type = 'submit'的情况。

    function func_4() {
        document.getElementById("fm_a").submit()
    }

上述实现了将输入的文件提交到后台,通过视图函数处理请求。

def fileUpload1(request):
    testFile = request.FILES.get("test_file3")
    file_path = os.path.join("static",testFile.name)
    data = {"status":"ok","index":file_path}
    f = open(file_path,"wb")
    for line in testFile.chunks():
        f.write(line)
    f.close()
    return HttpResponse(json.dumps(data))

回调函数:图片预览

function loadData(ths) {//当iframe中数据加载后执行onload对应的函数
var data = ths.contentWindow.document.body.innerHTML; //取得body中的字符串

var data_par = JSON.parse(data);//解析json字符串

var ele = document.createElement("img");
ele.src = "/"+data_par.index; //解析后的字典中的索引赋值给img对象的src属性
$("#preview").append(ele);
}

 ajax的三种方式实现文件的上传

认识FormData()对象,可以看做一个特殊的字典,在其里面可以封装数据,包括文件,消息,相对于采用字典传输数据的方式,他的优势在于能够传输文件,而字典不行。

1、jQuery

        <input type="file" name="test_file1" id="input_a">
        <a onclick="submitajax()" href="#">上传</a>
    function submitajax() {
        var testdata = new FormData();
        testdata.append("k",document.getElementById("input_a").files[0]);
        $.ajax({
            url:"/file_upload/",
            type:"POST",
            data:testdata,
            success:function (arg) {

            },
            processData:false,//需要加上这两个参数,表示不对数据进行处理,就是不让jquery对数据处理
            contentType:false,
        })
    }

2、原生XMLHttpR

<input type="file" id="input_file_c" onchange="submitajax_3()">
    function submitajax_3() {
        var data = new FormData();
        data.append("k",document.getElementById("input_file_c").files[0]);
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {

        };//回调函数
        xhr.open("POST","/file_upload_3/");
        //xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
        xhr.send(data)
    }

采用FormData对象提交数据和采用字典方式提交还有一点不同,不需要想后台提交请求头,字典方式组织的数据需要,不然request.POST上没有数据。jquery提交会自动处理数据会加上请求头,因此需要设置processData:false,

def fileUpload_3(request):
    print(request.POST)
    print(request.GET)
    print(request.FILES)
    testFile = request.FILES.get("k")
    file_path = os.path.join("static",testFile.name)
    data = {"status":"ok","index":file_path}
    # print(testFile.name)
    print(testFile.size)
    f = open(file_path,"wb")
    for line in testFile.chunks():
        f.write(line)
    f.close()
    return HttpResponse(json.dumps(data))

3、iframe和from

                    <iframe style="display: none;" id="upload_iframe" name="upload_iframe"></iframe>
                    <form method="POST" action="/{{ username }}/upload-avatar/" enctype="multipart/form-data"
                          target="upload_iframe"id="upload_fm">
                        {% csrf_token %}
                        <img id="previewImg" src="/{{ user_obj.img }}"
                             style="border-radius: 50%;height: 70px;width: 70px"/>
                        <div class="text">点击图片更换(<a href="#">撤销</a>)</div>
                        <input id="avatarImg" name="avatar_img" type="file" class="img-file"onchange="submit_img()"/>
                    </form>
        function submit_img() {
            document.getElementById("upload_fm").submit();
        }

 Jsonp和跨域访问

浏览器都有同源策略;同源策略是浏览器最核心最基本的安全功能。同源是指,域名、协议、端口相同。

同源策略分为两种:

1、DOM同源策略

2、XMLHTTPRequest同源策略

不允许使用XHR对象向不同源的服务器地址发起HTTP请求

同源策略是为了浏览器上网的安全,但是由于有了同于策略,引起了跨域访问的问题。

JSONP跨域原理:

script标签不会受到同源策略的影响,动态创建script标签,利用src跨域。

    <div id="div_jsonp_content"></div>
    <div href="" class="btn" onclick="func_jsonp()">点击</div>
    function func_jsonp() {
        var ele = document.createElement("script");
        ele.src = "http://127.0.0.1:8000/jsonp-test/";//跨域访问,执行路径为下面一处贴的代码
        document.head.appendChild(ele);
    document.head.removeChild(ele);   } function f_jsonp(arg) { $("#div_jsonp_content").html(arg); }

上述第一个函数1、先创建script标签,2、利用src跨域访问3、在head中添加标签4、移除标签

上述第二个函数,函数名和返回的字符串外层包裹相同,arg为内层字符串。

path('jsonp-test/', views.jsonp_test),//url需要跨域的服务器

def jsonp_test(request):
    return HttpResponse("f_jsonp('jsonp_test')")

 ajax有跨域访问的自动处理方式:对应的服务器返回同上。

<div href="" class="btn" onclick="func_jsonp1()">点击</div>
    function func_jsonp1() {
        $.ajax({
            url:"http://127.0.0.1:8000/jsonp-test/",
            type:"POST",
            dataType:'JSONP',
        })
    }
    function f_jsonp(arg) {
        {#$("#div_jsonp_content").html(arg);#}
        console.log(arg)
    }

ajax跨域指定返回的回调函数:

<div href="" class="btn" onclick="func_jsonp1()">点击</div>
    function func_jsonp1() {
        $.ajax({
            url:"http://127.0.0.1:8000/jsonp-test/",
            type:"GET",
            dataType:'JSONP',
            jsonp:"callback",
            jsonpCallback:"ffff",
        })
    }
    function ffff(arg) {
        {#$("#div_jsonp_content").html(arg);#}
        console.log(arg)
    }

服务器部分与先前有一些不同的地方

不同之处在视图处理函数,如下:

def jsonp_test(request):
    name = request.GET.get("callback")
    return HttpResponse("%s('jsonp_test')"%name)

 

posted on 2018-10-08 15:10  andyAngelo  阅读(111)  评论(0编辑  收藏  举报