最近在项目中遇到了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的变种,先解绑再绑定;过程稍微复杂。
强烈推荐事件委托的形式处理类似问题。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。