1

在 CompositeView 中,我像这样实现了无限滚动

List.Foo extends Marionette.CompositeView

  initialize: (collection) ->
    @page = 1
    $(window).on('scroll', @loadMore)

  loadMore: =>
    if _nearBottom
      @page++
      App.vent.trigger('list:foo:near_bottom', @page)

  _nearBottom =>
    $(window).scrollTop > $(document).height - $(window.height) - 200

# Then I have the controller to process the event "list:foo:near_bottom", 
# to ask for adding one more page of data in collection.

该代码基本上按预期工作。但是我觉得它不能令人满意,因为我认为这个 ComposteView 监视了一些超出其范围的 DOM 事件,也就是窗口级 DOM 事件。

我想使用布局来观看此类事件并进行广播,但我的顶级布局似乎仍然不够广泛,无法覆盖窗口/文档 :)

我的问题是,在 Marionette 中观看此类窗口/文档级 DOM 事件的更好结构是什么?谢谢!

4

1 回答 1

1

这个问题很久没有回答了,我在那个项目中改变了实现,所以我没有碰它。

Nguyen 的评论提供了非常好的观点,并提醒我回顾这个问题。

我也对Nguyen的观点有了新的认识。

有些东西必须是全球性的,我们无法避免。

这些事情包括但不限于:

  • 路线
  • 页面滚动
  • 页面加载
  • 窗口调整大小
  • 全局按键
  • ...

Backbone 有 Routes 来处理路由事件。其他的东西不是那么重要也不是那么流行,但它们仍然需要像路由一样对待。

在我看来,更好的方法是:在全局级别观察全局 DOM 事件,发送 App 事件,而不管谁可能对它感兴趣。

如果我重新做这个功能,我会做这样的事情(伪代码)

# App
App.on "initialize:after", ->
  @startHistory()
  @navigate('somePath', trigger: true) # Normal steps
  App.module('WindowWatcher').start()

# WindowWatcher module
ExampleProject.module "WindowWatcher", (WindowWatcher, App, Backbone, Marionette, $, _) ->
  class Watcher
    constructor: ->
      @watchPageScroll

    watchPageScroll: ->
      $(window).on('scroll', @_checkScroll)

    _checkScroll: ->
      if @_nearBottom:
        App.vent.trigger(scroll:bottom)

    _nearBottom:
      $(window).scrollTop > $(document).height - $(window.height) - 200

  WindowWatcher.on 'start' ->
    new Watcher()

然后List.Foo控制器将根据自己的喜好观看 App 事件scroll:bottom,并提供下一页。

可能还有其他部分对此事件感兴趣,例如在页脚视图中弹出一个按钮说你在底部,或者另一个通知说如果你想看到更多你需要注册等。他们也可以收听应用程序由于 Marionette 的美丽,无需管理窗口级别的 DOM。

重要更新 如果您直接在控制器内部而不是在模块级别观看 App vents,请确保控制器将停止侦听此通风口,否则侦听器将增加,App.vents这是内存泄漏。

# FooController
onClose: ->
  App.vent.off 'scroll:bottom'
于 2013-12-07T03:53:19.617 回答