2

コードを最初に見たい場合は、jsFiddle を次に示します。

私がやりたいことは簡単です。現在のルートのすべてのビューのレンダリングが終了した後、jQuery および jsPlumb ライブラリからいくつかの (実際には多くの) ビュー レイヤー Javascript コードを実行します。このソリューションからいくつかの助けを得て、ember-latest が更新されてafterRenderフックが含まれていることがわかった後、アップグレードすることにしました。私は今、万能のafterRenderフックを持っています。

私がdomに挿入しているすべてのビューにはblock、それらに関連付けられたクラスがあります。したがって、すべてのビューがdom内にあるかどうかを確認するためにテストしてきた方法は、使用$('.block').size()して、予想される数と一致するかどうかを確認することです。

ただし、アプリケーションでこのフックを使用しようとすると、いくつかの問題に直面します。afterRenderへの呼び出しの後、最初にルーターでを呼び出そうとしましたconnectOutlets。10個あるはずのdomのブロック数を出力すると、常に1ブロックしか得られません。

このコードを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) に対してコードが実行されることです。ただし、すべてのビューのレンダリングが終了した後、このコードを 1 回だけ実行したいと考えています。

私が作業しているビューにはネストされたデータがあることに注意してください。jsFiddle でこれを再現しようとしましたが、fiddle ですべての find と dandy が動作するように見えるという意味で失敗しました。ビューが大きくて複雑なため、同期の問題が発生している可能性がありますか? いずれにせよ、解決策について話し合う方法としてフィドルを使用でき、ローカルでテストできると思います。

この問題を回避するために私が試みた 1 つのハックは、 を使用して 500 ミリ秒の遅延後にコードを実行するようにスケジュールすることEmber.run.laterです。それは私のローカルマシンの問題を解決しました。ただし、これを行うためにタイマーを使用することは非常に羊の糞であり、さまざまなブラウザーまたはマシンがビューをレンダリングするのに時間がかかる場合があるため、確実に機能しません。

これは再現するのに時間がかかるものであり、解決策を見つけるためにすでに多くの時間を費やしてきました. ここで問題を再現するか、解決策を見つけるための助けをいただければ幸いです。

編集(回避策):この問題のトラブルシューティングを手伝ってくれてありがとう。同様の問題に関するこの投稿を見て、ルーターコード内に配置した次の一時的な回避策を思いつきました:

    # 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にアクセスできるようにする別のフックが必要だと感じていますが、おそらくここに何かが欠けています。

4

1 に答える 1

2

私はこの質問をKrisSeldenの前で実行しましたが、彼は「afterRenderは、その実行ループのレンダリングキューが完全にフラッシュされた後です。これは、複数のループを超えていると思います」と述べました。

最も可能性の高い可能性は、レコード配列をロードしていることです。おそらく、それは1つのアイテムから始まり、後でさらに9つのロードが行われます。データの読み込みを除外する場合、おそらくコードにEmber.run.nextまたはEmber.run.laterどこかにありますか?

于 2012-11-28T06:49:59.277 に答える