【问题标题】:What is the best way for showing a loading bar/spinner when a backbone collection is being fetched?获取主干集合时显示加载条/微调器的最佳方式是什么?
【发布时间】:2012-10-18 16:40:20
【问题描述】:

美好的一天!

最近我进入了主干/需求,并开始学习一些非常酷的东西。我正在尝试了解在获取主干集合时显示加载条/微调器的最佳做法是什么。以下是我发现使用的一些策略,用于触发集合上的 fetch/syncing 事件:

方法 1: 在应用程序启动之前覆盖主干的同步方法,并在该集合上触发“同步”事件

方法 2: 在应用程序启动之前覆盖主干的 fetch 方法,并在该集合上触发 'fetching' 事件

方法 3: 在定义集合时,重写 fetch() 方法并触发“fetching”事件,这样就可以监控任何实例的获取情况

方法四: 有人建议使用事件聚合,这样当视图调用 fetch() 获取集合时,该视图会触发事件。

这是我的情况:

  • 假设我有一个收藏 C
  • 有 2 个视图 V1 和 V2 可以访问它
  • V1 可以在 C 上调用 fetch,但 V2 不能
  • 当 C 开始 fetch 时,只有 V2 应该显示一个加载栏,并在 C 上调用 reset() 时将其关闭
  • 还有其他视图 V3、V4 等在获取 C 时可能也需要加载栏

显示加载栏的最佳机制是什么,同时保持严格的 MVC 模式完好无损?

选项 1: 视图是否应该监听集合上的“同步”事件?问题:如果调用了其他的 fetch()、save(),可能会显示加载栏

选项 2: 视图是否应该监听集合上的 'fetch()' 事件并采取相应措施?

选项 3: 一个视图在对集合调用 fetch() 时是否应该通知另一个视图?

选项 4:视图应该调用窗口上的获取方法还是事件聚合器?

也欢迎使用其他方法和选项。您的建议和意见将是最好的资源。谢谢。

【问题讨论】:

标签: model-view-controller events backbone.js


【解决方案1】:

以Backbone.View的上下文为例:

initialize: function() {
   this.state_loading();

   // assuming this.collection is your collection which is not fetched yet...       
   this.collection.bind('reset', this.state_loaded, this);
   this.collection.fetch();
},

state_loading: function() {
   this.el.addClass('st-loading');
},

state_loaded: function() {
   this.el.removeClass('st-loading');
}

现在 View 元素上的 .st-loading 类将简单地在您需要的任何地方显示一个微调器,例如

.ajax-spinner { backgrund: url('...'); display: none; }
.st-loading .ajax-spinner { display: block; }

现在想想你的选择:

方法 1: 不要覆盖库。下一个在生产环境中处理您的代码的人会因此而诅咒您。

方法 2: 你最好在收集时触发自定义事件,你不需要覆盖任何原生 Backbone 方法。同样,只有在您想不出好的解决方案时才会进行这种类型的黑客攻击。

方法 3: 我猜您的想法是每次加载某些内容时您都想显示一个微调器?我会为您的用户感到难过。

方法 4: 如果这发生在一个视图中,则不需要使用事件中心。最后,您可以在集合上触发自定义事件,并且父小部件可以订阅它。另一个考虑因素是您很可能需要在不同类型的元素中显示微调器,并且您需要为它们传递引用或选择器以用于不同的视图。现在如果你想要一个通用的解决方案,当然你可以给你的微调器提供相同的类应用程序,但是如果有一天你想删除它们,你会头疼的。您最好将这些内容本地化到您的视图中。

我们在一个由 Backbone 驱动的大型应用程序中遇到了类似的情况。为此,我们有一个扩展,我们将其应用于需要显示微调器的视图。它看起来有点像这样:

var state_loading: function() {
  if (arguments.length === 0 || arguments[0] === true) {
    this.el.addClass('st-loading');
  } else {
    this.el.removeClass('st-loading');
  }
}

var SomeView = Backbone.View.extend({
  initialize: function(options) {
    this.options = _.extend({}, this.options || {}, options || {});
    this.collection = this.options.collection;
    this.collection.bind('reset', this.render, this);
    this.state_loading(true);
    this.collection.fetch();
  },

  render: function() {
    this.state_loading(false);
    // your code...
  }
});

_.extend(SomeView.prototype, state_loading);

【讨论】:

  • 优秀的解决方案。我会记住这一点。我已经在想我不应该覆盖这个库,但因为这是我找到的最常见的解决方案,所以我对其进行了调整。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2017-07-10
  • 1970-01-01
  • 1970-01-01
  • 2014-01-24
  • 1970-01-01
  • 2022-06-15
  • 1970-01-01
  • 2011-04-23
相关资源
最近更新 更多