ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

前端提交表单数据的三种方式以及跨域实现

2021-05-17 16:55:36  阅读:150  来源: 互联网

标签:function obj 跨域 前端 表单 xhr k1 var document


这里讲的是不刷新页面的三种方式:

方式一:xmlrequest,也即原生方式

 <input id="k1" name="k1">
    <input type="submit"  onclick="nativeSubmit()" id="submit">
<script>
        function nativeSubmit() {
            var k1_v=document.getElementById("k1").value
            var data={'k1':k1_v}
            data=JSON.stringify(data)
            var xhr_obj=new  XMLHttpRequest()
            xhr_obj.open("post","/test")
            xhr_obj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); //request.body
            xhr_obj.send(data)
            xhr_obj.onreadystatechange=function () {
                if (xhr_obj.readyState == 4 && xhr_obj.status == 200) {
                        alert(xhr_obj.responseText);
                }
            }
         }
</script>

表单处理过程:收集数据-->发送数据-->接收数据处理

原生方式中,通过选择器收集标签的取值,在open函数中指定提交的方式和目标url,在send中发送post请求的数据(如果用get,则在open里面的url部分用?k=v的形式发送),回调函数则通过触发onreadystatechange事件在执行,readyState有多个值,对应数据处理的不同阶段,当等于4时则表示数据接收完毕

这里加了个:xhr_obj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); //request.body

这里因为post请求默认放在body里面,只有加上这个头部,django才会把body的数据处理放到request.POST里面,ajax处理会有这部分,所以这里也设置

方式二:ajax

    <input id="k1" name="k1">
    <input type="submit"  id="submit">
    <script src="/static/js/jquery-3.5.1.min.js"> </script>
    <script>
        $("#submit").click(function () {
            var k1_v=$("#k1").val()
            var data={'k1':k1_v}
            $.ajax({
                type:"POST",
                url:"/test",
                data:data,
                success(arg){
                    alert(arg)
                }
            })

        })
</script>

ajax封装了原生的语法,使用更简单,缺点就是需要额外加载jquery文件,对于一些流量紧张的应用不适用

方式三:form+iframe标签

  <iframe id="ifr" name="iframe"   style="display: none"></iframe>
<form action="/test" method="POST" target="iframe">
    <input id="k1" name="k1" >
    <input type="submit"  onclick="ifr1()" id="submit">
</form>

<script>
function ifr1(){
        document.getElementById("ifr").onload=reload;
    }
 {# 这里为什么不直接在iframe标签那里绑定reload事件呢?#}
 {# 因为会报错,如果iframe放在script上面会报reload函数找不到,如果放在下面则document找不到 #}
 {# 这是iframe的特殊之处,原因待查明 #}
function reload() {
        var content = this.contentWindow.document.body.innerHTML;
        alert(content)

    }
</script>

form表单通过target(值即iframe的name的值)与iframe关联,参数的设定跟直接form表单提交一样,差别在于回调函数的返回值在iframe里面,iframe类似一个小Windows对象,值放在document的body里面

这里<input type="submit" onclick="ifr1()" id="submit">,click事件处理在submit之前,所以可以直接这么写

前面的例子都是对字符串进行处理,若需要对文件进行处理,则可以用FormData对象进行封装

 <input id="k1" type="file" name="k1">
    <input type="submit"  onclick="nativeSubmit()" id="submit">
<script>
        function nativeSubmit() {
            var k1_v=document.getElementById("k1").files[0]
            console.log(k1_v)
            var data=new FormData()
            data.append("k1",k1_v)
            var xhr_obj=new  XMLHttpRequest()
            xhr_obj.open("post","/test")
            xhr_obj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); //request.body
            xhr_obj.send(data)
            xhr_obj.onreadystatechange=function () {
                if (xhr_obj.readyState == 4 && xhr_obj.status == 200) {
                        alert(xhr_obj.responseText);
                }
            }
         }
</script>
debug:

1.Refused to display 'http://127.0.0.1:8000/test' in a frame because it set 'X-Frame-Options' to 'deny'.

    原因:现代浏览器采用X-Frame-Options HTTP标头,该标头指示是否允许在框架或iframe中加载资源。如果响应包含标头值为的标头,SAMEORIGIN则浏览器将仅在请求源自同一站点的情况下将资源加载到框架中。如果将标头设置为,DENY则无论哪个站点发出请求,浏览器都将阻止资源加载到框架中。

解决方法有以下三种:

<1>注销掉

    'django.middleware.clickjacking.XFrameOptionsMiddleware'中间件

<2>处理函数前加上装饰器:

from django.views.decorators.clickjacking import xframe_options_exempt

@xframe_options_exempt

<3>在setting中设置:

    X_FRAME_OPTIONS = 'SAMEORIGIN'

2.jsonp和cors头部实现跨域

问题:当form提交请求时,有同源限制,比如我的网站是a.com,我提交请求也是向a.com提交,当我向b.com提交请求的的时候,因为浏览器会判断同源限制,会导致收到的数据不显示
例子:


   <button onclick="getvalue()">点击获取值</button>
    返回值是:<input id="k1" name="k1">
<script src="/static/js/jquery-3.5.1.min.js"> </script>
<script>
    function getvalue() {
        $.ajax({
            url:"http://127.0.0.1:9000/test1",
            type:"get",
            success(arg) {
            $("#k1").val(arg)
    }
        })
    }
</script>

报错:
前端提交表单数据的三种方式以及跨域实现

解决:

方式一:cors头部

最简单的是取消限制,服务端在响应请求的时候,在http头部加上:

Access-Control-Allow-Origin :*
客户端看到这个头部会取消同源限制

服务端代码:

def test1(request):
    ret=HttpResponse("hello")
    ret["Access-Control-Allow-Origin"]="*"
    return ret

方式二:jsonp

jsonp的原理在于利用其它可以跨域的标签,比如<script>、<img>等标签的src属性不受同源限制,jsonp就是动态创建这些标签,取得值后删除
<img>的src获取到数据后会渲染成图片,而在img标签中似乎没法获取图片的值,所以这里我用<script>标签

<script>标签的src获取到数值会以js的方式处理,所以如果我们服务端返回一个在前端已经定义的函数执行形式,比如func(),那么当客户端收到返回值就会执行对应函数,也就达到了回调函数的功能

前端代码:

 <button onclick="getvalue()">点击获取值</button>
    返回值是:<input id="k1" name="k1">
<script>
     var url="http://127.0.0.1:8000/test1"
    function getvalue() {
        var s_ele=document.createElement("script")
        s_ele.src=url
        document.body.appendChild(s_ele)
        document.body.removeChild(s_ele)
    }
    function func(arg) {
            document.getElementById('k1').value=arg

服务端代码:

def test1(request):
    ret=HttpResponse("func('hello')")
    ret["Content-Type"]="text/javascript"
    return ret

ajax的前端代码则更为简单,只要在dataType赋值jsonp,ajax默认就会以jsonp的形式跨域取值,代码如下:

 <button onclick="getvalue()">点击获取值</button>
    返回值是:<input id="k1" name="k1">
    <script src="/static/js/jquery-3.5.1.min.js"> </script>
<script>
    function getvalue() {
        $.ajax({
            url:"http://127.0.0.1:8000/test1",
            dataType:"jsonp"
        })
    }
    function func(arg) {
            $("#k1").val(arg)
    }
</script>

debug:

1.test:1 Refused to execute script from 'http://127.0.0.1:8000/test1' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.

解决:HttpResponse返回设置头部:Content-Type;"text/javascript"

标签:function,obj,跨域,前端,表单,xhr,k1,var,document
来源: https://blog.51cto.com/linzb/2781754

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有