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表單中並進行提交 :)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM