5

質問に入る前に。Event Loop とは、 http://en.wikipedia.org/wiki/Event_loopを参照していることを述べさせてください。これはブラウザが実装するものです。詳細については、http: //javascript.info/tutorial/further-javascript-features/events-and-timing-depthを参照してください。

この質問は難しくて長いので、我慢してみてください! そして、私はすべての答えに感謝します!


そう。現在、私が理解しているように、JavaScript には単一のメイン スレッドがあります (つまり、ほとんどのブラウザー環境で)。したがって、次のようなコード:

for (var color = 0x000; color < 0xfff; color++) {
    $('div').css('background-color', color.toString(16));
}

黒から白へのアニメーションを生成しますが、コードが処理された後にレンダリングが行われるため、それはわかりません (次のティックが発生すると、ブラウザーはイベント ループに入ります)。

アニメーションを見たい場合は、次のようにします。

for (var color = 0x000; color < 0xfff; color++) {
    setTimeout(function() {
        $('div').css('background-color', color.toString(16));
    }, 0);
}

上記の例では、setTimeout がブラウザのイベント ループ スタックに新しいイベントをプッシュするため、目に見えるアニメーションが生成されます。このスタックは、何も実行されていない後に処理されます (次に何をすべきかを確認するためにイベント ループに入ります)。

この場合、ブラウザーは 0xfff (4095) イベントをスタックにプッシュしているようです。各イベントは、その間にレンダリング プロセスで処理されます。それで、私の最初の質問 (#1) は、レンダリングが正確にいつ行われるかということです。イベント ループ スタック内の 2 つのイベントの処理の間に常に発生しますか?


2 番目の質問は、私が提供した javascript.info ウェブサイト リンクのコードに関するものです。

...
  function func() { 
    timer = setTimeout(func, 0)
    div.style.backgroundColor = '#'+i.toString(16)
    if (i++ == 0xFFFFFF) stop()
  }

timer = setTimeout(func, 0)
....

ここでの私の質問は、ブラウザーが新しい「レンダリング」イベントを、イベント ループ スタックに到達するたびにプッシュするdiv.style. ... = ...かどうかです。しかし、setTimeout-call のために最初にイベントをプッシュしませんか? それで、ブラウザは次のようなスタックになりますか?

setTimeout event
render event

setTimeout 呼び出しが div スタイルの変更前に処理されたので? スタックがそのように見える場合、次にブラウザーがイベント ループに入ったときに setTimeout のコールバックを処理し、次のようになると思います。

rendering event
setTimeout event
rendering event

前の setTimeout 呼び出しで生成されたレンダリング イベントを続行しますか?

4

2 に答える 2

6

Q1: 必ずしもそうではありません。ブラウザはさまざまな程度で最適化を実装しています。たとえば、コストのかかるレイアウトの再計算をトリガーする前に、いくつかのスタイル変更を収集するのを待つ場合があります。したがって、答えは次のとおりです。特定のブラウザに依存します。

これを試してください: http://taligarsiel.com/Projects/howbrowserswork1.htm#Render_tree_construction (ドキュメントの日付は 2009 年 10 月 - つまり、十分に最新です)

Q2: レンダリングは JS の実行と必ずしも同じではありません。これは 2 つの異なるエンジンです。この JS エンジンはレンダリングを担当せず、レンダリング エンジンとのインターフェースにすぎません。2 番目の質問に対する主なメッセージは、JS がレンダリング エンジンから独立していることです。ブラウザー (または Web ページ) は Javascript を必要としないことを思い出してください。その主な目的は、CSS スタイル ルールに基づいて HTML をレンダリングすることです。Javascript は、HTML (実際には DOM ツリー) とスタイル ルールを操作する 1 つの方法にすぎません。

スタイル定義を読み取ることでレンダリングを強制できることに注意してください。この時点で、レンダリング エンジンは未解決のスタイル変更を処理するしかありません。特に、位置の変更が含まれる場合はそうです。そのため、多くのスタイル変更を行ったり、多くの要素を追加したりする前に、レンダリング ツリーからオブジェクトを削除する必要があります (たとえば、display:none - visibility:hidden を設定するだけでは十分ではありません。これは、要素のサイズがレイアウトに考慮されるためです)。多くの行が 1 つずつテーブルに追加されます (「for」ループ)。

質問の一部ではありませんが、display:none と visibility:hidden の違いについて言及したばかりなので、ダイアログのような hidden position:absolute 要素を追加する際にも考慮されます。絶対配置された要素がいずれかの方法を使用して隠されている場合でも、目に見える違いはありませんが、内部的には大きな違いがあります。visibility:hidden を使用して隠されている場合、要素はレンダリング ツリーの一部であり、display:none を使用している場合はそうです。いいえ。そのため、何度も切り替える必要がある要素がある場合は、visibility:hidden を使用する必要があります。これは、「表示」スタイルが「なし」と「ブロック」の間で切り替えられると、ブラウザーは最初にそれをレンダリングする必要があるためです。

于 2011-03-05T12:28:24.287 に答える
1

あなたが言及した記事は、Javascriptのみを考慮しています。ブラウザではさらに多くのことが行われます。リフローと再描画は、より多くのことによってトリガーされる/トリガーされる可能性があります。詳細については、次のリンクを参照してください。

この目的で setTimeout を使用することはありません。

編集: コメントによると、推奨される方法はrequestAnimationFrameを使用することです。これを書いている時点では、これはほとんどのブラウザーの不安定なリリースでのみ利用できます。ただし、クロスブラウザ アクセスを提供する利用可能なライブラリいくつかあり、必要に応じて setTimeout を使用するようにフォールバックします。

古いブラウザと新しいブラウザで動作する例については、このデモをご覧ください: http://paulirish.com/2011/requestanimationframe-for-smart-animation/

于 2011-03-05T12:32:25.063 に答える