使用带有嵌套视图的`afterRender`钩子

时间:2012-11-28 02:19:16

标签: ember.js

Here is the jsFiddle if you like to see code first

我想要做的很简单:在当前路线中的所有视图完成渲染后,从jQuery和jsPlumb库中执行一些(实际上很多)视图层Javascript代码。在从this solution获得一些帮助并发现ember-latest刚刚更新为包含afterRender钩子后,我决定升级。我现在拥有全能的afterRender钩子。

我插入dom的所有视图都有一个block类与之关联。所以我一直在测试以查看所有视图是否都在dom中的方式是使用$('.block').size()并查看它是否与预期数量匹配。

但是当我尝试在我的应用程序中使用此挂钩时,我遇到了一些问题。在调用afterRender之后,我首先尝试在路由器中调用connectOutlets。当我打印出dom中的块数时,我总是只有1个块,而应该有10个。

如果我将此代码放在我的本地didInsertElement视图的block中:

didInsertElement: () ->
    knob = this.$("##{@get 'knobId'}")
    name = this.$(".name")
    main = this.$(".main") #block html content will be injected into main
    knob.hide()

    Ember.run.scheduleOnce('afterRender', this, ()->
      console.log ">> block count: ", $(".block").size()
    )
    ...

然后我得到以下输出:

>> block count: 1
>> block count: 10
>> block count: 10
>> block count: 10
>> block count: 10
>> block count: 10
>> block count: 10
>> block count: 10
>> block count: 10
>> block count: 10

出于某种原因,第一次迭代我只在dom中得到1 ,之后我得到了所有10.我不知道为什么。但是这里的主要问题是如果我把钩子放在didInsertElement里面,代码就会根据数据执行任意数量的视图(在这个例子中为10)。但是我只希望在所有视图完成渲染后运行此代码。

请注意,我正在使用的视图具有嵌套数据。我试着reproduce this on jsFiddle,,但是我失败的意思是它似乎可以找到所有找到和花花公子的小提琴。也许是因为我的观点庞大而复杂,导致了一些同步问题?无论如何,我认为我们可以使用小提琴作为讨论解决方案的一种方式,我可以在本地测试它。

我尝试解决此问题的一个方法是使用Ember.run.later安排我的代码在延迟500ms后运行。这确实解决了我本地机器上的问题。但是,使用计时器执行此操作非常不适合使用,因为不同的浏览器或计算机可能需要更长时间才能呈现视图。

这是一个重现的,我已经花了很多时间试图找到解决方案。我很感激在这里重现问题或找到解决方案的任何帮助。

编辑(解决方法):感谢您帮助我解决此问题,并查看this post about a similar problem,我想出了以下临时解决方法,我将其置于路由器中代码:

    # Keep trying until there are two or more blocks in DOM
    blocksLoaded = ->
      console.log "blocks number ...: ", $('.block').size()
      if $('.block').size() > 1
        console.log "Yay!...we have ", $('.block').size()
        startTraversingBlocks()
      else
        Ember.run.next(this, ()->
          blocksLoaded()
        )

    blocksLoaded()

输出:

blockies number ...: 0
blockies number ...: 1
blockies number ...: 1
blockies number ...: 1
...
blockies number ...: 1
blockies number ...: 10
Yay!...we have 10

正如Luke所指出的,这里的问题是我的嵌套视图正在多个RunLoops上呈现。当我刷新浏览器时,我每次都会得到不同数量的blockies number ...: 1输出,在我的测试过程中会有4到10次。

在我看来,这不是一个很好的解决方案,但它似乎适用于我的用例。我觉得这里需要另一个钩子,它允许一个人在保证视图中的所有元素都可以通过jQuery选择器访问时访问DOM,但也许我在这里遗漏了一些东西。

1 个答案:

答案 0 :(得分:2)

我把这个问题告诉了Kris Selden,他说“afterRender在渲染队列之后完全被刷新了,因为我认为这已经超过了一个循环”

最有可能的是你有一个记录阵列加载。也许它从一个项目开始,然后再加载9个。如果您排除数据加载,可能代码中某处有Ember.run.nextEmber.run.later