在网页上要操作文件通常会使用INPUT[type=file]
控件,但这个控件的设计很蛋疼。它不像其它编程语言中文件选择后会触发一个事件,只是让上面的文字改变,而这个改变可能会触发change
事件而已。对于文字没改变的选择,change
事件则不会触发。
当INPUT[type=file]
控件上已经选择过一次文件之后,再次点击它选择同一个文件时change
事件就不会触发。因为第二次选择后里面的文字和第一次是一样的,没有改变。还有个更蛋疼情况是有些浏览器会自动记住控件上的文字,即使页面关闭后重新打开还是会恢复到原来的文字。这时候选择同路径的文件也不会触发change
事件。
这些问题都是INPUT[type=file]
控件蛋疼的设计所引起的,从一般渠道无法解决这个问题。有人建议在点击INPUT[type=file]
控件时先清空其文字,这样在选中文件之后自然可以触发change
事件。但一些浏览器上对INPUT[type=file]
控件的值是只读的,要清空恐怕不容易。但从这里我们可以推广出另一种偷天换日的解决方案。既然值无法写入,为何我们不创建一个新的INPUT[type=file]
把旧的替换掉呢?这么一来,需要解决的问题就剩下事件绑定了。这可以通过在容器上绑定事件,之后通过冒泡的方式来获取,而不把事件绑定到目标元素上的方法来解决。下面就是一个不太漂亮的解决办法(由于一些兼容代码写着麻烦,这里直接用了jQuery):
运行
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script>
$(function(){
form.reset(); //清除浏览器记录的上次记录
var file;
$(form).on("change","#file",function(e){
//输出选中结果
console.log(this.value);
//每次选中都保存旧元素,并使用新的控件替换
$(this).clone().replaceAll(file=this);
}).submit(function(){
//提交时把之前保存的旧元素替换回去
$("#file").replaceWith(file);
});
});
</script>
<form id="form">
<input type="file" name="file" id="file"><br/>
<input type="submit" />
</form>
input:file
onchange
事件无法读取解决方法
最近做项目,移动端的多文件上传,使用input:file
读取文件
<input type='file' name='file' multiple accept='image/*' capture='camera'>
但是在移动端 设置 multiple
属性是不起作用的,设置此属性PC端可以多选而移动端无法多选。
我使用的解决方案是动态添加 input:file
标签。,每添加一个标签就出发一次click
事件读取文件。然后选择相片并且将相片显示在页面上。
一开始直接在通过JQuery绑定change
事件,结果发现无法触发;接着用原生,也不行;最后直接将事件绑定到标签上也是不行的,全都触发不了change
事件。
查询过后发现是input:file
的问题
进入页面执行JS时,先将表单 RESET
掉form,reset();
然后将change
事件绑定到form
表单上,采用事件委托。顺利解决。