1

ビューがレンダリングされた後に jquery プラグイン (たとえば、dom にテーブルを挿入する) を呼び出したい場合、window.setTimeout() でこれを行う以外に可能性はありますか?

このコードは仕事をします(1ミリ秒のタイムアウト;それは奇妙です):

Route.HomeRoute = Ember.Route.extend({
        renderTemplate: function() {

            this.render("home");   // render the home view

            window.setTimeout(function() {
                $(".tables").insertTables();    // this would add a table
            }, 1);

        }
    })

しかし、このコードは機能しません:

Route.HomeRoute = Ember.Route.extend({
        renderTemplate: function() {

            this.render("home");   // render the home view

            $(".tables").insertTables();    // this would add a table

        }
    });

Ember.View.didInsertElement() があることは知っていますが、そのため、親ビューにコールバックを設定する必要があり、上記のコード例が期待どおりに機能しないのはなぜだろうと思っていました。

どうもありがとう!

4

2 に答える 2

2

私の答えが 100% 正確かどうかはわかりませんが、次のように説明できると思います。

問題は、 render() メソッドが同期的に仕事をしていると思うことだと思います。しかし、そうではありません。代わりに、HomeView のレンダリングをスケジュールします。レンダリングはEmber の RunLoop にスケジュールされます。2 番目の例では、コードはレンダリングをスケジュールし、すぐにその DOM 要素にアクセスしようとします(.tables はホーム テンプレートの一部だと思います)。しかし、ビューは現時点ではレンダリングされません! 1 ミリ秒のタイムアウトが含まれているため、最初の例は機能します。このタイムアウト中に、Ember RunLoop が開始され、その魔法が開始されます。レンダリングを実行し、その後 CPU が再び解放されると、タイムアウト関数を呼び出すことができます。

実際にここでやりたいことは次のとおりdo something on my DOM, when the View was successfully renderedです。これは、setTimeout を使用せずに Ember で実行できます。次のコードは、RunLoop にアクセスし、RunLoop の最後に実行される機能をスケジュールします。

Ember.run.next(function() {
     $(".tables").insertTables();    // this would add a table
});

Ember の詳細を理解したい場合は、RunLoop に関する記事をご覧ください

最後になりましたが、Route でこのような DOM 操作を行うのはまったく厄介です。あなたのルートは、そのようなものから常に解放されるべきです。要素とセレクター、および jQuery プラグインは、View レイヤーでのみ使用する必要があります。他のすべてが悪いようです。このアプローチを選択した理由について、詳細を共有したいと思われるかもしれません。これよりも優れた解決策がある可能性があります。

于 2013-03-21T09:28:26.757 に答える
0

2 番目の例が機能しない理由は、おそらくEmber.js の Run Loopが原因です。 this.render現在の実行ループの後半で dom 挿入をスケジュールします。

DOM の挿入は実行ループの最後で行われ、 を使用するsetTimeoutことで、実行ループの終了後にプラグインを呼び出しているため、テンプレートが DOM に挿入されたことが保証されます。(1ms は必要ありません。0ms はおそらく機能します)

特に Ember.js の初心者にとって、この実行ループは非常に複雑であると言うかもしれません。問題は、理想的には、アプリ開発者に対して透過的であることです。その副作用が発生する理由は、DOM 操作がルーターで処理されるべきではないためです。

私の最初の反応はdidInsertElement、 、またはビュー内のコードまたはフックを使用するように指示することでした。これは、DOM 操作が発生する場所であるためです。しかし、あなたはそれを認識しているようで、何らかの理由で使用できません(十分な情報がないため、確認も否定もできません)。

あなたへの私のアドバイスは、でそれを行うために最善を尽くしてくださいdidInsertElement.

于 2013-03-21T09:29:18.100 に答える