【问题标题】:Unexpected behaviour when previewing images before uploading上传前预览图像时出现意外行为
【发布时间】:2017-07-06 20:47:15
【问题描述】:

我一直致力于在上传多张图片之前预览它们,并尝试使用@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);
    });
});

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

这是我在不调试的情况下运行脚本时的屏幕截图:

这是使用 js 调试器单步执行时的结果屏幕截图

【问题讨论】:

    标签: javascript jquery html css image


    【解决方案1】:

    短篇小说:

    将循环更改为

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

    let keyword in the for loop

    注意,for 循环中的let 可能无法像预期的那样对 IE11 和 Edge 起作用。您可以将跨度的创建移动到 reader.onload 事件中以针对这些浏览器进行调整(尽管您的 id 代必须更改)。

    长篇大论:

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

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

    稍后,reader.onload 异步调用返回 for 循环完成(其中i 处于循环的最大值),并将结果 imgs 附加到#span_(max i).

    更新:好的,所以 let 可能并非所有地方都支持,caniuse 表示截至 2017 年 7 月已达到 80%。

    为了获得一致的结果,请将 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 版本)。

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

    【讨论】:

    • 我尝试使用 let 语句 @duncan-smith 切换我的 for 循环,但结果没有改变。在我的 IDE(phpstorm 2017.1.4)中,'let' 被指示为一个错误,提示“当前 JavaScript 版本不支持 let 定义”。我正在使用 yii2 框架,当前安装的 jquery 版本是 2.2.4。我目前正在测试的浏览器是 mozilla firefox 54.0(32 位)、firefox 开发者版 55.0b6(64 位)和 chrome 59.0.3071.115(官方构建)(64 位)。知道问题出在哪里吗?
    • @natral,我已经更新了我的答案。看看它是否适合你。
    • 这对@duncan 很有帮助。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-26
    • 1970-01-01
    相关资源
    最近更新 更多