入力ハンドラをデバウンスする

入力ハンドラは、フレームの完了をブロックしたり、不要なレイアウト処理を追加したりする可能性があるため、アプリのパフォーマンスの問題の原因となる可能性があります。

入力ハンドラは、フレームの完了をブロックしたり、不要な追加レイアウト処理を引き起こしたりする可能性があるため、アプリのパフォーマンスの問題の原因となる可能性があります。

概要

  • 長時間実行される入力ハンドラは、スクロールをブロックする可能性があるため、使用しないでください。
  • 入力ハンドラでスタイルを変更しないでください。
  • ハンドラをデバウンスします。イベント値を保存し、次の requestAnimationFrame コールバックでスタイル変更を処理します。

長時間実行される入力ハンドラを回避する

最速の場合、ユーザーがページを操作すると、ページのコンポジタ スレッドがユーザーのタップ入力を受け取り、コンテンツを移動するだけです。これにより、JavaScript、レイアウト、スタイル、ペイントを行うメインスレッドでの作業は不要になります。

軽量スクロール。コンポジタのみ。

ただし、touchstarttouchmovetouchend などの入力ハンドラをアタッチする場合、preventDefault() を呼び出してタップ スクロールを停止する可能性があるため、コンポジタ スレッドはハンドラの実行が完了するのを待つ必要があります。preventDefault() を呼び出さなくてもコンポーザは待機しなければならないため、ユーザーのスクロールがブロックされ、スタッタリングやフレームの欠落が発生する可能性があります。

スクロールが重い。JavaScript でコンポーザがブロックされている。

つまり、実行する入力ハンドラはすべて迅速に実行し、コンポジタがその処理を実行できるようにする必要があります。

入力ハンドラでスタイルを変更しない

スクロールやタップなどの入力ハンドラは、requestAnimationFrame コールバックの直前に実行されるようにスケジュールされます。

これらのハンドラのいずれかで視覚的な変更を加えると、requestAnimationFrame の開始時にスタイルの変更が保留されます。その後、requestAnimationFrame コールバックの開始時に視覚プロパティを読み取ると、大規模で複雑なレイアウトとレイアウト スラッシングを回避するのアドバイスに沿って、強制同期レイアウトがトリガーされます。

スクロールが重い。JavaScript でコンポーザがブロックされている。

スクロール ハンドラをデバウンスする

上記の両方の問題の解決策は同じです。視覚的な変更は常に次の requestAnimationFrame コールバックにデバウンスする必要があります。

function onScroll (evt) {

    // Store the scroll value for laterz.
    lastScrollY = window.scrollY;

    // Prevent multiple rAF callbacks.
    if (scheduledAnimationFrame)
    return;

    scheduledAnimationFrame = true;
    requestAnimationFrame(readAndUpdatePage);
}

window.addEventListener('scroll', onScroll);

また、これにより入力ハンドラを軽量に保つという利点もあります。計算コストの高いコードでスクロールやタップなどの処理をブロックしなくて済むため、これは非常に便利です。