问题是我的想法。有人能帮我吗?
在我的html文件的<script>
标记中,我有:
window.ondragover = function(e){return false;}
window.ondragenter = function(e){return false;}
window.ondrop = function(e){
var files = e.target.files || e.dataTransfer.files;
for (var i = 0, file; file = files[i];i++){
var img = document.createElement('img');
img.height = 200;
img.width = 200;
img.style.background = 'grey';
document.body.appendChild(img);
var reader = new FileReader();
reader.onload = function(){
img.src = reader.result;
}
reader.readAsDataURL(file);
}
return false;
}
但是当我在浏览器上删除多个图像文件时,只有最后一个图像文件被加载并显示在最后一个img元素中,其他图像文件保持灰色。
答案 0 :(得分:6)
正如@chazsolo所说:
有一种感觉这是由于你在循环中使用img。由于reader.onload是异步的,for循环已经完成,img指向最后一个
您可以在循环(let - MDN)中使用let
代替var
来解决此问题。这将为每个img
和reader
提供一个块范围,允许异步读取器方法仍然访问该特定循环运行的实际值。
window.ondragover = function(e){return false;}
window.ondragenter = function(e){return false;}
window.ondrop = function(e){
var files = e.target.files || e.dataTransfer.files;
debugger;
for (var i = 0, file; file = files[i];i++){
let img = document.createElement('img');
img.height = 200;
img.width = 200;
img.style.background = 'grey';
document.body.appendChild(img);
let reader = new FileReader();
reader.onload = function(){
img.src = reader.result;
}
reader.readAsDataURL(file);
}
return false;
}
更新:var vs let
那么为什么var
不能怀疑它?
我尝试用一些实际例子来解释let
和var
的区别。
变量声明,无论它们出现在何处,都会在任何声明之前处理 代码被执行。
这引出了以下示例(最后请注意错误,这是由剪切的插件产生的):
使用var 的声明
/**
In this example, 'a' is declared after it is used. This doesn't matter, as the
declaration of 'a' will be processed before running the code. This means a is
initialized with 'undefined' but is valid. Also the scope of a lies within the
execution context, that's why it is even available outside of the loop.
**/
console.log("---------");
console.log("Example Declaration var");
console.log("---------");
for (var i = 0; i < 2; i++) {
console.log(a); // a is declared but undefined on the 1st run, afterwards it get redeclared and owns the value from the last run.
var a = i;
}
console.log(a); // a is even available out here as still same execution context.
&#13;
a
之前的a
的每次重新声明都保留了。它不是一个新的&#34;实例&#34;。
那么如果我们在循环中使用异步函数会发生什么?
与var的异步功能
/**
This example shows you the effects, if you use a async function within a loop.
As the loop will be executed way under 100 miliseconds (which is the time out
of the async function), c will have the same value for all exections of the
async mehtod, which is the value assigned by the last run of the loop.
**/
console.log("---------");
console.log("Example effects async var");
console.log("---------");
for (var i = 0; i < 2; i++) {
var c = i;
setTimeout(function() {
console.log(c); //var does redeclare, therefor c will be modified by the next loop until the last loop.
}, 100);
}
&#13;
确实,总是相同的输出(适应你的问题,总是相同的img元素和文件)
让我们看看let
声明
/**
In this example, 'b' is declared after it is used with let. let will be processed
during runtime. This means 'b' will not be declared when used. This is an invalid
state. let will give a strict context within the loop. It will be not available
outside. let has a similar behavior as a declaration in Java.
**/
console.log("---------");
console.log("Example Declaration let");
console.log("---------");
for (var i = 0; i < 2; i++) {
try {
console.log(b); //b is not declared yet => exception
} catch (ex) {
console.log("Exception in loop=" + ex);
}
let b = i;
console.log("Now b is declared:"+b);
}
try {
console.log(b); // b is not available out here as the scope of b is only the for loop. => exception
} catch (ex) {
console.log("Exception outside loop=" + ex);
}
console.log("Done");
&#13;
let
具有更具体的范围。这导致更有意的编码。
最后,我们看到当我们在循环中使用let
和异步函数时会发生什么。
使用 的异步功能
/**
This example shows you the effects, if you use a async function within a loop.
As the loop will be executed way under 100 milliseconds (which is the time out
of the async function). let declares a new variable for each run of the loop,
which will be untouched by upcoming runs.
**/
console.log("---------");
console.log("Example effects async let");
console.log("---------");
for (var i = 0; i < 2; i++) {
let d = i;
setTimeout(function() {
console.log(d); //let does not redeclare, therefor d will not be modified by the next loop
}, 100);
}
&#13;
<强>结论强>
在您的示例中,您总是以最后分配的img
元素和最后分配的file
结束。您执行相同操作的次数与阵列中的文件相同,只是最后一个文件。