關於type=file;事件只執行一次的問題


    最近在項目中遇到了type = file change事件只執行一次的問題;在網上百度了一下發現仍是有很多人遇到了一樣的問題;提供了的解決方案也是五花八門;總結起來大概有3-5種吧。html

 

1.html代碼中onchange=xxx;指定jquery

2.執行一次後,在綁定一次ajax

3.執行一次後,替換原來的type-filechrome

4.移除舊元素,生成一個如出一轍的服務器

5.利用live(如今是On)方法(其實就是事件委託)app

 



下面一一驗證上面的方法;並在最後給出最佳方案(如今先不驗證ajax請求的場景,博客衆說紛紜,讓我以爲有ajax和沒有ajax,上述方法是有區別的)ide

 

方法1:代碼:函數

   <script>
function filechange() {
     alert("change");
}
 </script>

  <input type="file" id="Org_avatar" name="Org_avatar[]" 
                                onchange="filechange()" class="u-fileInput-small-but" />



  <input type="file" id="Org_avatar" name="Org_avatar[]" 
                                onchange="aler('aaaaaa')" class="u-fileInput-small-but" />


chromeIE8下驗證,都可以觸發屢次。spa

 

方法2;執行一次後再綁定一次;設計

代碼以下:

                 $("#Org_avatar").bind('change',filechange);
                function filechange() {
                    alert("bind change");
                     $("#Org_avatar").bind('change',filechange);
                }


 

這是有問題的;代碼陷入不斷的遞歸中執行這次數會隨着點擊次數的2n-1方執行;繞不過彎的動手試試;再次綁定時先解綁以前的函數,時能夠達到效果的;代碼以下:

 

                 $("#Org_avatar").bind('change',filechange);

                function filechange() {
                    alert("bind change");
                    //$("#Org_avatar").unbind('change',filechange);
                     $("#Org_avatar").bind('change',filechange);
                }


 

方案3

                var element = document.getElementById("Org_avatar");
                //  $("#Org_avatar").bind('change',filechange);
                 //$("#Org_avatar").change(filechange);
                element.onchange = filechange;
                function filechange() {
                    alert("bind change");
                      $("#Org_avatar").replaceWith(' <input type="file" id="Org_avatar" name="Org_avatar[]" class="u-fileInput-small-but" />')
                }

無論是,bind,change 仍是原生的onchanges事件在chrome IE8下局執行一次;因此這個方法應該行不通;(其實jquerybind,change的底層實現仍是原生的onchange,詳情請看jquery源碼,謝謝)

 


方案4,通過驗證也不可行;其實很明顯;你移除那個元素;在添加一個新元素;明顯此時沒有事件綁在這個新元素上(以前綁定的,是綁定在被替換的元素上)

 

                var element = document.getElementById("Org_avatar");
                //  $("#Org_avatar").bind('change',filechange);
                 $("#Org_avatar").change(filechange);
               // element.onchange = filechange;
                function filechange() {
                   $("#Org_avatar").remove();
                    var input = '<input type="file" id="Org_avatar" name="Org_avatar[]" index="a" class="u-fileInput-small-but"/>';
                    $("#nihao").append(input);
                }


方案5:利用on

 

這個方法使用過事件委託,或者處理過,給還沒有出現的元素綁定事件(好比,一個彈窗在用戶某個操做後,才顯示處理;可是要求在觸發彈窗的click;觸發某個事件)。實現的原理很簡單 ,就是事件委託。這裏利用on或者live甚至是delegate;底層原理都是利用addEventListener 或者attachEvent;須要主要的是委託的元素必須是在頁面上顯示的,而且是該元素的祖先(通常委託在body上)

      $("body").on('change','#Org_avatar',function () {
                    alert("nihao");

       });
             
             
      var e = document.getElementById("Org_avatar");
       e.addEventListener("change",function(){//attachEvent
              alert("nihao");
       })

 

因此這個方法是行的通的。在chromeIE8下驗證,都可以觸發屢次。

 



好了幾種方案講完了;可是感受問題又來了;上傳功能咱們通常會設計ajax請求上傳圖片到後臺服務器;可是上面幾種方案的表現,好像不同。。

下面進行驗證,並說明結果。

 

方法1:驗證ok

                function filechange() {
                    alert("nihao");
                           ajaxFileUpload();
    
                }

 

方法2:解綁以後,再綁定,驗證ok

 

                                 $("#Org_avatar").bind('change',filechange);
                function filechange() {
                    alert("nihao");
                    ajaxFileUpload();
                    $("#Org_avatar").unbind('change',filechange);
                     $("#Org_avatar").bind('change',filechange);
                };


方法3:不可行;不知道爲何網上有些博客說這樣能夠;有知道爲何的告訴我一聲。

方法4:不可行;不知道爲何網上有些博客說這樣能夠;有知道爲何的告訴我一聲。

 

 $("#Org_avatar").bind('change',filechange);
                function filechange() {
                    alert("nihao");
                    ajaxFileUpload();
                   $("#Org_avatar").replaceWith(' <input type="file" id="Org_avatar" name="Org_avatar[]" class="u-fileInput-small-but" />');
                };


方法五,我已經在咱們項目中使用了,因此很明顯能夠的。

                $("body").on('change','#Org_avatar',function () {
                    var allowImgageType = ['jpg', 'jpeg', 'png', 'gif'];
                    var file = $("#Org_avatar").val();
                    //獲取大小
                    var byteSize = getFileSize('Org_avatar');
                    //獲取後綴
                    if (file.length > 0) {
                        if (byteSize > 2048) {
                            alert("上傳的附件文件不能超過2M");
                            return;
                        }
                        var pos = file.lastIndexOf(".");
                        //截取點以後的字符串
                        var ext = file.substring(pos + 1).toLowerCase();
                        //console.log(ext);
                        if ($.inArray(ext, allowImgageType) !== -1) {
                            ajaxFileUpload();
                        } else {
                            alert("請選擇jpg,jpeg,png,gif類型的圖片");
                        }
                    }
                    else {
                        alert("請選擇jpg,jpeg,png,gif類型的圖片");
                    }
                });


說在最後

因此在我看來,方法1,2(先解綁,再綁定),5是可行的。


方法3,4不知道是否是以訛傳訛的結果,我也在求證中。


我的認爲最好的方法仍是利用事件委託。成本低,效果高;給不存在的元素和被隱藏的元素綁定事件,這種方案使咱們最經常使用的。


方法1,感受屬於上世紀的東西;不解耦,不利於代碼維護,可複用等等。

方法2的變種,先解綁再綁定;過程稍微複雜。

強烈推薦事件委託的形式處理相似問題。

相關文章
相關標籤/搜索