文件输入触发更改事件两次(或更多次)

时间:2016-08-09 08:15:55

标签: javascript

我隐藏了一个基本的input[file]元素。当您单击#holder弹出文件资源管理器时。但是选择一个文件会触发console.log()行执行两次(在我的计算机上)。

注意:以下代码会崩溃我的Chrome标签。

您最好将其作为单独的文件运行。无法提供"工作"演示,但这是我最接近MCVE



var element = document.getElementById('holder');

element.onclick = function(e) {
  var input = document.getElementById('file-input');
  input.click();
  input.addEventListener("change", function(evt) {
    console.log(evt);
    Phimij.addFiles(input.files);
  }, false);
};

#holder {
  border: 10px dashed #ccc;
  width: 300px;
  height: 300px;
  margin: 20px auto;
}
#holder.hover {
  border: 10px dashed #333;
}
#file-input {
  display: none;
}

<div id="holder">
  <input type="file" multiple id="file-input" />
</div>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:3)

click个事件冒泡了祖先树。这意味着点击input会冒泡到您的#holder元素,并点击您的click处理程序。在click上的#holder处理程序中,您可以在click上触发input事件。这就是你的浏览器崩溃的原因:你已经触发了无限循环。

解决方法是将click挂钩input并告诉它不要冒泡(传播);看到标记的行(但请继续阅读,下面的进一步说明):

var element = document.getElementById('holder');
// **** Added vvvv
document.getElementById('file-input').addEventListener("click", function(evt) {
  evt.stopPropagation();
}, false);
// *** Added ^^^^
element.onclick = function(e) {
  var input = document.getElementById('file-input');
  input.click();
  input.addEventListener("change", function(evt) {
    console.log(evt);
    // Phimij.addFiles(input.files);
  }, false);
};
#holder {
  border: 10px dashed #ccc;
  width: 300px;
  height: 300px;
  margin: 20px auto;
}
#holder.hover {
  border: 10px dashed #333;
}
#file-input {
  display: none;
}
<div id="holder">
  <input type="file" multiple id="file-input" />
</div>

还有一些我要改变的事情。您每次 <{1}} change时, 一个click处理程序<{1}}你真的只想这样做一次。我还会在触发点击之前添加该处理程序。

因此,为了它的价值,我会做出一些改变:

#holder
var element = document.getElementById('holder');
var input = document.getElementById('file-input');

element.addEventListener("click", function() {
  input.click();
}, false);

input.addEventListener("click", function(evt) {
  evt.stopPropagation();
}, false);
input.addEventListener("change", function(evt) {
  console.log(evt);
  // Phimij.addFiles(input.files);
}, false);
#holder {
  border: 10px dashed #ccc;
  width: 300px;
  height: 300px;
  margin: 20px auto;
}
#holder.hover {
  border: 10px dashed #333;
}
#file-input {
  display: none;
}