【问题标题】:Backbone Marionette: Don't display view before all images have loadedBackbone Marionette:在所有图像加载之前不显示视图
【发布时间】:2014-12-22 17:15:22
【问题描述】:

我正在显示一个 CompositeView,其中每个模型都有一个属性,该属性是图像的 url。如果我只是在一个区域中显示视图,图像还没有完成加载,这看起来不太性感(它们在加载时显示)。

我想等到所有图像都加载完毕,然后再显示视图。现在,我试图通过延迟图像加载来使其工作,但这可能不是正确的方法(也许这应该在模型上完成?)。

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);
        });

      });

    }

  };

});

【问题讨论】:

  • 您是在问这是要在模型中完成的事情还是什么?我认为该视图应该处理图像加载
  • 不。模型问题只是一个子问题:) 我想要最好的解决方案。
  • 最好的解决方案是检查所有图像是否都已加载,然后渲染您的视图。您可以将该逻辑(图像加载检查)提取到集合中。看here 和here

标签: backbone.js marionette


【解决方案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() 可以是和选项,这将在整个页面加载后触发。

谢谢。

【讨论】:

  • 这看起来很有希望(明白这个笑话吗?)。您能否在我的代码上下文中详细说明一下?
  • 谢谢。你帮我写了一个解决方案。你喜欢吗? (我知道 loadImage 函数的位置可能不是很好,但到目前为止它是我在应用程序中唯一使用它的地方)。
【解决方案2】:

我最终做了这样的事情(灵感来自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();
    }

  };

});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-15
    • 1970-01-01
    • 2016-06-29
    • 1970-01-01
    • 2014-03-30
    • 1970-01-01
    • 2016-01-05
    • 1970-01-01
    相关资源
    最近更新 更多