首页 文章

用于图像预览的HTML5 fileAPI中的Javascript需要澄清

提问于
浏览
0

我正在查看新的HTML5文件API,用于显示要上载的图像的预览 . 我搜索了一些代码,几乎每个例子都有相同的结构,几乎相同的代码 . 我不介意复制,特别是当它工作时,但我需要理解它 . 所以我试着理解代码,但我被困在一个区域,需要有人来解释这个小部分:

代码引用HTML表单输入字段,选择文件时会在img标记中显示预览图像 . 没有什么花哨 . 简单 . 这是在消除所有噪音后:

$('input[type=file]').change(function(e) {
     var elem = $(this);
     var file = e.target.files[0];
     var reader = new FileReader();

   //Part I could not understand starts here
   reader.onload = (function(theFile) {
     return function(e) {
        var image_file = e.target.result            
        $('#img_id').attr('src',image_file);
     };
   })(file);
   reader.readAsDataURL(file);
   //Upto here
 });

我认为reader.onload需要分配一个普通的事件处理程序,所以我将上面标记的整个部分替换为:

reader.readAsDataURL(file);
    reader.onload = function(e) {
      var image_file = e.target.result;         
      //#img_id is the id of an img tag 
       $('#img_id').attr('src',image_file)
    };

它起到了我预期的作用 .

问题:上述简化代码缺失的原始代码是什么?我知道它是一个函数表达式返回一个函数然后调用它...但是为了什么?在教程下复制了太多的原始代码,但没有很好的解释 . 请解释 . 谢谢

1 回答

  • 1

    当然 .
    函数包装函数,这里用于记住您正在查看的文件的特定目的 .

    使用您的确切代码库可能不会出现问题,但如果您有多个上传小部件,并且想要显示一行预览:

    var my_files = [].slice.call(file_input.files),
    
        file, reader,
    
        i = 0, l = my_files.length;
    
    
    for (; i < l; i += 1) {
        file = my_files[i];
        reader = new FileReader();
    
        // always put the handler first (upside down), because this is async
        // if written normally and the operation finishes first (ie:cached response)
        // then handler never gets called
        reader.onload = function (e) {
            var blob_url = e.target.result,
                img = new Image();
    
            img.src = blob_url;
            document.body.appendChild(img);
        };
        reader.readAsDataUrl(file);
    }
    

    这应该都可以 . ......除了......而且它清晰可读 .

    正在解决的问题只是这样:

    我们正在处理异步处理程序,这意味着回调触发时 file 的值不一定相同,就像之前一样......

    有很多方法可以解决这个问题 .
    几乎所有这些都没有生成随机的id / sequence-number /基于时间的哈希来检查返回,依赖于闭包 .

    为什么我要创建一个完整的管理系统,当我可以将它包装在一个函数中并完成?

    var save_file_reference_and_return_new_handler = function (given_file) {
        return function (e) {
            var blob_url  = e.target.result,
                file_name = given_file.name;
    
            //...
        };
    };
    

    所以如果你在函数的顶部(循环上方)有这个,你可以说:

    reader = new FileReader();
    reader.onload = save_file_reference_and_return_new_handler(file);
    reader.readAsDataUrl(file);
    

    现在它会正常工作 .

    当然,JS人并不总是觉得有必要编写命名函数,只是为了将一个项目存储在闭包中以便以后记住...

    reader.onload = (function (current_file) {
        return function (e) {
            var blob_url  = e.target.result,
                file_name = current_file.name;
        };
    }(file));
    

相关问题