溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

關(guān)于type=file;事件只執(zhí)行一次的問(wèn)題

發(fā)布時(shí)間:2020-07-07 00:18:19 來(lái)源:網(wǎng)絡(luò) 閱讀:7154 作者:水中月120 欄目:開發(fā)技術(shù)


    最近在項(xiàng)目中遇到了type = file change事件只執(zhí)行一次的問(wèn)題;在網(wǎng)上百度了一下發(fā)現(xiàn)還是有不少人遇到了同樣的問(wèn)題;提供了的解決方案也是五花八門;總結(jié)起來(lái)大概有3-5種吧。

 

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

2.執(zhí)行一次后,在綁定一次

3.執(zhí)行一次后,替換原來(lái)的type-file

4.移除舊元素,生成一個(gè)一模一樣的

5.利用live(現(xiàn)在是On)方法(其實(shí)就是事件委托)

 



下面一一驗(yàn)證上面的方法;并在最后給出最佳方案(現(xiàn)在先不驗(yàn)證ajax請(qǐng)求的場(chǎng)景,博客眾說(shuō)紛紜,讓我覺(jué)得有ajax和沒(méi)有ajax,上述方法是有區(qū)別的)

 

方法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下驗(yàn)證,均可以觸發(fā)多次。

 

方法2;執(zhí)行一次后再綁定一次;

代碼如下:

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


 

這是有問(wèn)題的;代碼陷入不斷的遞歸中執(zhí)行此次數(shù)會(huì)隨著點(diǎn)擊次數(shù)的2n-1方執(zhí)行;繞不過(guò)彎的動(dòng)手試試;再次綁定時(shí)先解綁之前的函數(shù),時(shí)可以達(dá)到效果的;代碼如下:

 

                 $("#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下局執(zhí)行一次;所以這個(gè)方法應(yīng)該行不通;(其實(shí)jquerybind,change的底層實(shí)現(xiàn)還是原生的onchange,詳情請(qǐng)看jquery源碼,謝謝)

 


方案4,經(jīng)過(guò)驗(yàn)證也不可行;其實(shí)很明顯;你移除那個(gè)元素;在添加一個(gè)新元素;明顯此時(shí)沒(méi)有事件綁在這個(gè)新元素上(之前綁定的,是綁定在被替換的元素上)

 

                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

 

這個(gè)方法使用過(guò)事件委托,或者處理過(guò),給尚未出現(xiàn)的元素綁定事件(比如,一個(gè)彈窗在用戶某個(gè)操作后,才顯示處理;但是要求在觸發(fā)彈窗的click;觸發(fā)某個(gè)事件)。實(shí)現(xiàn)的原理很簡(jiǎn)單 ,就是事件委托。這里利用on或者live甚至是delegate;底層原理都是利用addEventListener 或者attachEvent;需要主要的是委托的元素必須是在頁(yè)面上顯示的,并且是該元素的祖先(一般委托在body上)

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

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

 

所以這個(gè)方法是行的通的。在chromeIE8下驗(yàn)證,均可以觸發(fā)多次。

 



好了幾種方案講完了;但是感覺(jué)問(wèn)題又來(lái)了;上傳功能我們一般會(huì)設(shè)計(jì)ajax請(qǐng)求上傳圖片到后臺(tái)服務(wù)器;但是上面幾種方案的表現(xiàn),好像不一樣。。

下面進(jìn)行驗(yàn)證,并說(shuō)明結(jié)果。

 

方法1:驗(yàn)證ok

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

 

方法2:解綁之后,再綁定,驗(yàn)證ok

 

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


方法3:不可行;不知道為什么網(wǎng)上有些博客說(shuō)這樣可以;有知道為什么的告訴我一聲。

方法4:不可行;不知道為什么網(wǎng)上有些博客說(shuō)這樣可以;有知道為什么的告訴我一聲。

 

 $("#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" />');
                };


方法五,我已經(jīng)在我們項(xiàng)目中使用了,所以很明顯可以的。

                $("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("上傳的附件文件不能超過(guò)2M");
                            return;
                        }
                        var pos = file.lastIndexOf(".");
                        //截取點(diǎn)之后的字符串
                        var ext = file.substring(pos + 1).toLowerCase();
                        //console.log(ext);
                        if ($.inArray(ext, allowImgageType) !== -1) {
                            ajaxFileUpload();
                        } else {
                            alert("請(qǐng)選擇jpg,jpeg,png,gif類型的圖片");
                        }
                    }
                    else {
                        alert("請(qǐng)選擇jpg,jpeg,png,gif類型的圖片");
                    }
                });


說(shuō)在最后

所以在我看來(lái),方法1,2(先解綁,再綁定),5是可行的。


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


個(gè)人認(rèn)為最好的方法還是利用事件委托。成本低,效果高;給不存在的元素和被隱藏的元素綁定事件,這種方案使我們最常用的。


方法1,感覺(jué)屬于上世紀(jì)的東西;不解耦,不利于代碼維護(hù),可復(fù)用等等。

方法2的變種,先解綁再綁定;過(guò)程稍微復(fù)雜。

強(qiáng)烈推薦事件委托的形式處理類似問(wèn)題。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI