HTML input[type=file]二次打开文件时不触发change事件

<input id="importInputFile" type="file"/>的change事件“$("#importInputFile").change(()=>{//xxx})”只能被触发一次,不管上传失败还是成功
在标签上绑定了<input id="importFile" onchange="javascript:$('#importFileName').val()"/> 也一样
原因:
在网页上要操作文件通常会使用input[type=file]控件。它选择后会触发一个事件,只是让上面的文字改变,而这个改变会触发change事件而已,并不会自动清空已选的value。对于文字没改变的选择,或者第二次选择,change事件则不会触发。所以需要手动清空元素的value,但是部分浏览器清空会无效果,所以保守的做法是直接替换这个file元素

这里我提供两种方法

个人推荐第一种,简单粗暴明了,自用没毛病。

(最近发现直接清空value在蛮多浏览器基本都奏效了。详情看第三点 2018-10-18)

一、

每次执行完你的change函数后替换一下原来的input type=file控件

function importMaterial(obj,type){
 
 $.ajax({             
    url: xxx,             
    type: "POST",             
    data: JSON.stringify(item),             
    headers: headersJson,             
    success: function (data) {            
    //xxx 
    },             
    error: function (data) {              
       console.log(data.responseText);     
    },            
    complete: function () {         
      $("#btn_uploadMaterial").replaceWith('<input type="file" id="btn_uploadMaterial" accept=".xls,.xlsx" οnchange="importMaterial(this,'+type+')"/>');                  //替换的内容可以与你原来的input一模一样,只要你执行替换,
               // 浏览器就会认为你这是个新的控件,之前的记录就会被清空
                //change事件就可以再次调用了             
    }        
 });
}

这里我还可以推广出另一种偷天换日的解决方案。既然值无法写入,为何我们不创建一个新的INPUT[type=file]把旧的替换掉呢?这么一来,需要解决的问题就剩下事件绑定了。这可以通过在容器上绑定事件,之后通过冒泡的方式来获取,而不把事件绑定到目标元素上的方法来解决。

二、

<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>

三、目前已兼容大部分浏览器,还蛮阔以

//皆为文件上传结束后再清空,否则会影响文件上传
1、jQ

$("#btn_uploadMaterial").val('');

2、vue

function fileChange(e){
    e.srcElement.value = "";
}

3、dom

document.getElementById("btn_uploadMaterial").value="";
发布了25 篇原创文章 · 获赞 10 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/xj932956499/article/details/80433037
今日推荐