Ember.js - jQuery-masonry + 无限滚动

4
我正在尝试在我的Ember项目中实现无限滚动和瀑布流效果。瀑布流的“砖块”是带有文本和图像的文章。目前,我可以在页面初始加载时显示第一页并应用瀑布流(但仍需要setTimeout,我正在尝试弄清楚如何消除它)。
我还编写了基本的无限滚动代码。现在,我只是从后端获取第二页。当滚动到页面底部时,将加载第二页的文章。我正在尝试找出如何在插入新页面时应用瀑布流。
$('#masonry-container').masonry('refresh')放在didInsertElement中不起作用,因为视图元素已经呈现,并且我只是将新元素附加到现有视图中。
是否有事件可以放置刷新操作?
以下代码在初始加载时应用瀑布流,然后在滚动到底部时加载第二页,但当前不会刷新瀑布流。
谢谢
路由:
App.Router.map ->
  @route 'posts', path: '/'

App.PostsRoute = Ember.Route.extend
  model: -> 
    App.Post.find()

    events:
      more: ->
        App.Post.query(page: 2) # hard code for now, next page will come from back end

视图:

App.PostsView = Ember.View.extend
layoutName: 'appLayout'
templateName: 'posts'
controller: 'posts'

didInsertElement: ->
  @scheduleMasony()
  $(window).bind('scroll', =>
    @.didScroll()
  )

scheduleMasony: -> 
  Ember.run.schedule('afterRender', @, @applyMasonry)

applyMasonry: ->
  setTimeout(-> 
    $('#masonry-container').masonry(
      itemSelector: '.box',
      columnWidth: 220,
      gutterWidth: 10,
      isFitWidth: true,
      isAnimated: true
    )
  2000)

didScroll: -> 
  if @isScrolledToBottom()
    @get('controller').send('more')

isScrolledToBottom: -> 
  distanceToTop = $(document).height() - $(window).height()
  top = $(document).scrollTop()
  top == distanceToTop

Templates:

app_layout.handlebars

...layout mark up...
<div id="container">
  {{yield}}
</div>
...more layout mark up...

posts.handlebars:

<div id="masonry-container" class="transitions-enabed infinite-scroll clearfix centered">
{{#each controller.content}}
  <div class="col2 box">
    <h3>{{title}}
    <img {{bindAttr src="imageUrl"}} >
    <p class="text">
      {{text}}
    </p>
  </div>
{{/each}}
</div>

application.handlebars

{{outlet}}

我刚刚编辑了我的答案,我拼错了 length,对此感到抱歉... - intuitivepixel
我的意思是 controller.content.length 中的 length 拼写成了 lenght,因此无法正常工作,我希望现在可以正常工作... - intuitivepixel
1个回答

1
当滚动到页面底部时,会加载第二页的帖子。我正在尝试弄清楚如何在插入新页面时应用砌体布局。
我猜你最好观察控制器的content长度,以便重新调用砌体布局,因为追加到DOM中的内容与您显示的帖子数量有关。
所以尝试像这样做:
App.PostsView = Ember.View.extend({
  layoutName: 'appLayout'
  templateName: 'posts'
  controller: 'posts'
  ...
  contentDidChange: function() {
    // check for 'inDOM' just to be sure
    // we don't run this unnecessarily 
    // when the view is not yet rendered
    if(this.get('state') === "inDOM") {
      applyMasonry();
    }
  }.observes('controller.content.length')
  ...
});

希望它有所帮助。

1
谢谢,将观察者放在content.length上并检查inDOM是否有效。我所做的唯一修改是在砖石应用/刷新函数中添加了一个去抖动,以便它不会为每个加载到页面上的内容触发。 - Bryan Cosgrove
@Bryan,你能否更新一下你的问题并分享你的解决方案吗?我也做了类似的事情,但还是没有成功。 - Hasib Mahmud

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接