您好,登錄后才能下訂單哦!
最近在項目中遇到了type = file change事件只執行一次的問題;在網上百度了一下發現還是有不少人遇到了同樣的問題;提供了的解決方案也是五花八門;總結起來大概有3-5種吧。
1.html代碼中onchange=xxx;指定
2.執行一次后,在綁定一次
3.執行一次后,替換原來的type-file
4.移除舊元素,生成一個一模一樣的
5.利用live(現在是On)方法(其實就是事件委托)
下面一一驗證上面的方法;并在最后給出最佳方案(現在先不驗證ajax請求的場景,博客眾說紛紜,讓我覺得有ajax和沒有ajax,上述方法是有區別的)
方法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" />
在chrome和IE8下驗證,均可以觸發多次。
方法2;執行一次后再綁定一次;
代碼如下:
$("#Org_avatar").bind('change',filechange); function filechange() { alert("bind change"); $("#Org_avatar").bind('change',filechange); }
這是有問題的;代碼陷入不斷的遞歸中執行此次數會隨著點擊次數的2的n-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下局執行一次;所以這個方法應該行不通;(其實jquery的bind,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"); })
所以這個方法是行的通的。在chrome和IE8下驗證,均可以觸發多次。
好了幾種方案講完了;但是感覺問題又來了;上傳功能我們一般會設計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的變種,先解綁再綁定;過程稍微復雜。
強烈推薦事件委托的形式處理類似問題。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。