• js实现无刷新表单提交文件,将ajax请求转换为form请求方法


    最近在做项目的时候遇到一个需要上传文件的需求,因为ajax请求是无法上传二进制文件流的,所以只能用form表单提交,而form提交有一个问题就是会使页面刷新,本文解决了form表单提交文件时页面刷新的问题。

    一、无刷新实现form提交文件

    将form的target指向为一个iframe就可以实现无刷新提交文件了,但关键是还需要看到后台返回的数据,所以还需要为该iframe注册一个回调函数,因为iframe和该页面在同域内,所以可以在iframe里可以调用该回调函数,就可以看到后台返回的数据了。实例如下:

    <body>
        <form method="post" target="targetFrame" action="#" enctype="multipart/form-data" id="fileupId">
            <input type="file" name="" id="">
        </form>
    
    <script>
        var ifmId = 'targetFrame';
            var iframe = document.createElement("iframe");
            document.body.appendChild(iframe);
            iframe.style.display = "none";
            iframe.contentWindow.name = ifmId;
            iframe.id = ifmId;
            
            iframe.callback = function(json) {
               success && success(json)
        }
    </script>
    </body>

    里面的js的作用主要是创建了一个iframe,并为iframe设置id和name,并为其注册回调函数。另外后台需要注意的有两点:

    1.后台返回的数据类型应为html,否则无法在iframe里面显示,举个栗子:<html><script>frameElement.callback({test:'test'})</script></html>

    ,其中{test:test}应该是后台返回的数据;

    2.ngix的http头应将x-Frame-Option设置为SAMEORIGIN,这样使页面可以在同域下能够被iframe调用;

    这样一来,一个可以不刷新页面上传文件的功能就做好了,但是我们整个的系统都是ajax完成的,如果临时改成form可能改变很大,那么有没有有个方法可以不用一个个的去改,直接用一个方法就可以将所有的ajax上传的内容都改成form呢

    二、动态转换所有数据到form表单内,并实现提交;

    这个方法总的来说分为三步:1.在打开页面的时候遍历所有需要提交的输入框或者文件上传等内容,并将其每一个添加到动态创建的form表单之中;2.将其中的上传文件按钮绑定表单中的文件上传input;3.当用户点击提交的时候自动填充除了文件外其他的form表单,并提交表单,获取返回数据。

    直接看代码:

        var newForm = function(){
            
            var conds = $('[data-cond]');
            var formDom = $('<form method="post" style="display:none;" enctype="multipart/form-data" id="fileupId"></form>')
            var textDom = $('<input type="text">');
            var fileDom = $('<input type="file">');
            conds.each(function(i, ele) {
                var _ele = $(ele);
                var key = _ele.data('cond').toString().trim();
                if (_ele.hasClass('select')) {
                    //下拉框
                    formDom.append($('<input type="text">').attr('name',key));
                }else if (_ele.hasClass('fileUp')) {
                    //文件
                    formDom.append($('<input type="file">').attr('name',key));
                    _ele.on('click',function(){
                        $("input[name="+ key +"]").click();
                    })
                }else{
                    formDom.append($('<input type="text">').attr('name',key));
                }
    
            });
            $('body').append(formDom);
            formDom.delegate('input','change',function(){
                var id = $(this).attr('name');
                var files = $(this).get(0).files[0];
                //判断文件类型
                if(!/.jpg$|.jpeg$|.gif|.png$/ig.test(files.name)){
                            alert('请选择图片文件~')
                    return false;
                }
                //判断文件大小
                if(files.size > 20480000){
                     alert('请上传20M内的文件~')
                    return false;
                }
                var name = files.name.replace(/(w{10})(w+)/,'$1..')
                //文件名筛选只显示前10个字符
                $('#'+id+'').text(name);
            })
            //formDom.hide();
        }                

    这个方法的目的主要是为了动态创建一个表单,并为html文件中的上传文件按钮与form内的上传文件输入框绑定,实现选择文件的功能,另外还用正则实现了文件类型、大小的筛选并选择性显示文件名的前十个字符,其中$('#'+id+'')就是相应的上传文件按钮,另外为想转换为form表单内的内容的dom添加标签[data-cond="xxx"],通过判断它的类来添加不同的Input。

    var form = function(opt){
            console.log()
            var dom = opt.dom;
            var success = opt.success || function() {};
            var preUrl = eking.global.preUrl;
            var postUrl = opt.postUrl || "";
            var iframeName = opt.iframeName;
            var conds = $('[data-cond]');
            var consObj = {};
            
            conds.each(function(i, ele) {
                var _ele = $(ele);
                var key = _ele.data('cond').toString().trim();
                if (_ele.hasClass('select')) {
                    //下拉框
                    $("input[name="+ key +"]").val(_ele.data('select').getValue());
                }else if (_ele.attr('type') == "text") {
                    //文本框
                    $("input[name="+ key +"]").val(_ele.val());
                }else if (_ele.attr('type') == "password") {
                    //密码框
                    $("input[name="+ key +"]").val(_ele.val());
                }else if (_ele.hasClass('span')){
                    $("input[name="+ key +"]").val(_ele.text());
                }
            });
            dom.attr({
                target: iframeName,
                action: preUrl + postUrl
            });
            var ifmId = 'targetFrame';
            var iframe = document.createElement("iframe");
            document.body.appendChild(iframe);
            iframe.style.display = "none";
            iframe.contentWindow.name = ifmId;
            iframe.id = ifmId;
            iframe.callback = function(json) {
               success && success(json)
               $("#targetFrame").remove();
            }
        }

    第二个函数就和我们一开始介绍的方法类似,不过将其进行了封装,添加了几个参数dom、success、preUrl、postUrl、iframeName,其中两个url是为了设置form表单提交的地址,dom则是在第一个函数中创建form表单,success则是数据传输后的回调函数。

    在目标页面刚打开时调用第一个函数,当用户点击提交时,调用第二个函数就可以实现转换输入内容到form表单中并进行提交 :)

  • 相关阅读:
    普通平衡树(treap与splay模板)
    NOIP2009T4 靶形数独
    单调队列模板
    NOIP2010引水入城
    数差
    NOIP2016DAY2T1 组合数问题
    NOIP2016 D2T3 愤怒的小鸟
    NOIP双栈排序
    膜拜
    斐波那契数列
  • 原文地址:https://www.cnblogs.com/cheerup/p/6260764.html
Copyright © 2020-2023  润新知