2014-10-27 79 views
3

Im显示一个CompositeView,其中每个模型都有一个属性,它是图像的url。如果我只是在区域中显示视图,图像尚未完成加载,这看起来不太性感(它们在加载时显示)。Backbone Marionette:在所有图像加载之前不要显示视图

我想在显示视图之前等待所有图像加载完毕。现在,我试图通过推迟图像加载来实现它,但这可能不是正确的方式(也许这应该在模型上完成)。

applications/list_view.js 

App.module("ApplicationsApp.List", function(List, App, Backbone, Marionette, $, _){ 
 

 
    List.Application = Marionette.ItemView.extend({ 
 
    tagName: 'li', 
 
    template: Templates.applications.application 
 
    }); 
 

 
    List.Applications = Marionette.CompositeView.extend({ 
 
    className: "applications", 
 
    template: Templates.applications.applications, 
 
    childView: List.Application, 
 
    childViewContainer: "ul" 
 
    }); 
 

 
});

applications/list_controller.js 

App.module("ApplicationsApp.List", function(List, App, Backbone, Marionette, $, _) { 
 

 
    List.Controller = { 
 

 
    listApplications: function() { 
 
     // Set layout 
 
     App.trigger("set:layout:authenticated"); 
 

 
     // Fetch the applications 
 
     var fetchingApplications = App.request('application:entities'); 
 

 
     $.when(fetchingApplications).done(function(applications) { 
 

 
     var applicationsListView = new List.Applications({ 
 
      collection: applications 
 
     }); 
 

 

 
     var deferreds = []; 
 

 
     applications.each(function(application) { 
 

 
      deferreds.push(function() { 
 
      var loader = new Image(); 
 
      loader.onload = function() { 
 
       console.log(application.get("image_path")); 
 
      }; 
 
      loader.src = application.get("image_path"); 
 
      }); 
 

 
     }); 
 

 
     $.when.apply($, deferreds).then(function() { 
 
      App.layout.mainRegion.show(applicationsListView); 
 
     }); 
 

 
     }); 
 

 
    } 
 

 
    }; 
 

 
});

+0

你是问,如果这东西在模型或什么办?我认为这种观点应该处理图像加载 – Dethariel 2014-10-27 14:12:33

+0

Naah。模型问题只是一个子问题:) 我想最好的解决方案。 – tolborg 2014-10-27 14:27:06

+0

最好的解决方案是检查是否加载了所有图像,然后渲染您的视图。您可以将该逻辑(图像加载检查)提取到集合。看看[这里](http://stackoverflow.com/questions/18974517/javascript-check-if-images-are-loaded-before-gameloop)和[这里](http://stackoverflow.com/questions/15587330/测试,如果所有的图像被加载) – 2014-10-27 14:35:46

回答

1

我觉得你的做法是正确的,我会尽量封装数据/图像加载功能于一体,采用一个版本库可能是

$.when(applicationsRepository.getAll()).then(function (apps) { 
     var appsView = new App.Views.ApplicationListView({ collection: apps}); 
     App.layout.mainRegion.show(appsView); 
    }); 

因此,该代码将是你控制器的一部分,因为你已经拥有了它,当资源库完成加载控制器只呈现在视图中的数据,类似的东西到服务器端MVC与仓库,

getAll()将包含您现在在控制器上加载数据和图像的代码,该存储库将作为您的木偶应用程序的额外模块。

所以你的方法GETALL将会像

var getAll = function() { 
     var deferred = $.Deferred(); 
     _getAll(function (apps) { 
      deferred.resolve(apps); 
     }); 
     return deferred.promise(); 
    }; 

    var _getAll = function (callback) { 
     //code to create the app collection 
     apps.on("reset", function(apps){ 
      //load images 
      //callback(apps); 
     }); 
     apps.fetch({ reset: true }); 
    }; 

要确定并进行最后的图像加载后的一些行动(回调),我可能会用一个计数器设定为图像的总数量(从集合),并在每次执行装载处理程序时递减它。 $(window).load()可能是和选项,这将在整个页面加载后触发。

谢谢。

+0

这似乎很有前途(得到的笑话?)。您能否在我的代码中详细阐述一下? – tolborg 2014-10-27 21:27:26

+0

这很有趣,我编辑了我的答案,希望它有帮助。 – 2014-10-27 21:52:53

+0

谢谢。你帮我写了一个解决方案。你觉得怎么样?(我知道loadImage函数的位置可能不是很好,但到目前为止,它是我使用它的应用程序中的唯一位置)。 – tolborg 2014-10-27 22:45:39

0

最后我做这样的(由Wait for image to be loaded before going on启发):

applications/list_controller.js 

App.module("ApplicationsApp.List", function(List, App, Backbone, Marionette, $, _) { 
 

 
    List.Controller = { 
 

 
    listApplications: function() { 
 
     self = this; 
 
     // Set layout 
 
     App.trigger("set:layout:authenticated"); 
 

 
     // Fetch the applications 
 
     var fetchingApplications = App.request('application:entities'); 
 

 
     // Perform actions when applications have been fetched 
 
     $.when(fetchingApplications).done(function(applications) { 
 

 
     // Load all images in applications 
 
     var imgLoaders = []; 
 

 
     applications.each(function(application) { 
 
      var src = application.get("image_path"); 
 
      imgLoaders.push(self.loadImage(src)); 
 
     }); 
 

 
     // Perform actions when images have been loaded 
 
     $.when.apply($, imgLoaders).done(function() { 
 
      var applicationsListView = new List.Applications({ 
 
      collection: applications 
 
      }); 
 
      App.layout.mainRegion.show(applicationsListView); 
 
     }); 
 

 
     }); 
 

 
    }, 
 

 
    loadImage: function(src) { 
 
     var deferred = $.Deferred(); 
 
     var img = new Image(); 
 
     img.onload = function() { 
 
     deferred.resolve(); 
 
     }; 
 
     img.src = src; 
 
     return deferred.promise(); 
 
    } 
 

 
    }; 
 

 
});

相关问题