上载前预览图像时出现意外行为

时间:2017-07-06 20:47:16

标签: javascript jquery html css image

我一直在预览多张图片,然后才上传并尝试使用@ ratan-paul对"Preview an image before it is uploaded"的响应非常有用。但是,当我尝试稍微调整代码时,我得到了一个相当意外的结果。我所做的是为每个<span>创建一个<image>标记,以添加一些样式选项。这是我最终得到的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 个答案:

答案 0 :(得分:1)

短篇小说:

将循环更改为

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

let keyword in the for loop

注意,let循环中的for可能无法像IE11和Edge那样工作。您可以将跨度的创建移动到reader.onload事件中以调整这些浏览器(但您的id代将不得不改变)。

长篇故事:

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

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

稍后,{/ 1}}异步调用在 for循环完成后返回(其中reader.onload处于循环的最大值),并追加结果{ {1}}到i

更新:好的,所以img可能无法在任何地方得到支持,截至2017年7月,caniuse将其置于80%。

要获得一致的结果,请将#span_(max i)元素的创建移至let事件:

span

请注意,这些onload元素的创建最终可能会出现故障;如果您在添加时按顺序添加它们,请查看使用Promise.all(或jQuery版本)。

另请注意,我没有对上述情况进行测试,因此可能需要进行一些按摩。