2017-07-06 93 views
1

我一直在预览多个图像,然后尝试使用@ ratan-paul对"Preview an image before it is uploaded"的响应非常有用。但是,当我试图调整代码有点我得到了一个意想不到的结果。我所做的是为每个<image>创建一个<span>标签以添加一些样式选项。这里是jQuery代码我结束了:在上传前预览图像时发生意外的行为

$(function() { 
    var span_id = ""; 
    function readURL(input) { 
     for(var i =0; i< input.files.length; i++){ 
      var span = $('<span>'); 
      span_id = "span"+i; 
      span.attr('id',span_id); 
      span.appendTo('#img-previews'); 
      if (input.files[i]) { 
       var reader = new FileReader(); 
       reader.onload = function (e) { 
        var img = $('<img id="dynamic">'); 
        img.attr('src', e.target.result); 
        img.attr('height','150px'); 
        img.attr('width','200px'); 
        img.appendTo("#"+span_id); 
       }; 
       reader.readAsDataURL(input.files[i]); 
      } 
     } 
    } 

    $("#imgUpload").change(function(){ 
     readURL(this); 
    }); 
}); 

现在奇怪的是,当我运行上面的代码我创建的每个图像的<span>标签,但所有的图像得到塞进创建的最后一个<span>。另一方面,如果我调试脚本,我会得到想要的结果,其中每个图像都插入到它自己的<span>标记中。我对此感到困惑,所以如果任何人有任何想法,为什么会发生这种情况,或者如何避免这种情况,将不胜感激。

这是当我运行该脚本无需调试的截屏: Screen grab of unexpected behavior

这里是通过与JS调试 Result when stepping through a JS debugger

回答

1

短篇小说踩当结果的截屏:

你的循环改为

for(let i =0; i< input.files.length; i++){ 

let keyword in the for loop

注意,letfor循环可能无法正常工作正如人们所预料的IE11和边缘。您可以将创建的范围移动到reader.onload事件中,以调整这些浏览器(您的代的ID将不得不更改)。

长的故事:

使用var i =0实例i在整个循环,而let i =0其绑定到当前迭代。

发生了什么事情是for循环触发异步调用reader.onload,该循环被添加到JS事件循环以供将来解析,并且for循环继续进行下一次迭代。 重要位:在下一次迭代中,前面的reader.onload尚未解决

一段时间以后,该reader.onload异步调用 for循环后返回完成(其中i处于用于循环中的最大值),并追加所得img s到#span_(max i)

更新:OK,所以let可能不支持无处不在,caniuse将其定在80%,截至7月2017。

对于一致的结果,移动span元件的创建到onload事件:

function readURL(input) { 
    for(var i =0; i< input.files.length; i++){ 
     if (input.files[i]) { 
      var reader = new FileReader(); 
      reader.onload = function (e) { 
       var span = $('<span>'); 
       var uniqueId; 
       do { //simple loop to generate a unique id 
        uniqueId = 'img-' + (Math.random()+1).toString(36).substring(2, 7); 
       } while ($('#' + uniqueId).length > 0); //redo loop if id not unique 
       span.attr('id', uniqueId); 
       span.appendTo('#img-previews'); 

       var img = $('<img>'); 
       img.attr('src', e.target.result); 
       img.attr('height','150px'); 
       img.attr('width','200px'); 
       span.append(img); 
      }; 
      reader.readAsDataURL(input.files[i]); 
     } 
    } 
} 

注意,这些span元素的创建可能最终被乱序;如果您希望它们按添加的顺序排列,请查看Promise.all(或jQuery版本)。

另外请注意,我没有测试过上述所以一些按摩可能需要。

+0

我试着用let语句@duncan-smith切换我的for循环,但结果没有改变。在我的IDE(phpstorm 2017.1.4)中,'let'被表示为“当前JavaScript版本中不支持当前定义”的错误。我正在使用yii2框架,并且当前安装的jquery版本是2.2.4。我目前正在测试的浏览器是Mozilla firefox 54.0(32位),firefox开发者版本55.0b6(64位)和chrome 59.0.3071.115(官方版本)(64位)。任何想法是什么问题? – natral

+0

@natral,我已经更新了我的答案。看看它是否适合你。 –

+0

伟大的,帮助了很多@邓肯。谢谢! – natral