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="";

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章