入力ハンドラは、フレームの完了を妨げ、追加の不要なレイアウト作業を引き起こす可能性があるため、アプリのパフォーマンス上の問題の原因となる可能性があります。
入力ハンドラは、アプリ内のパフォーマンスの問題の潜在的な原因となります。これらはフレームの完了を妨げ、追加の不要なレイアウト作業の原因になります。
概要
- 長時間実行される入力ハンドラを避けて、スクロールがブロックされないようにします。
- 入力ハンドラではスタイルを変更しないでください。
- ハンドラをデバウンスします。イベント値を格納し、次の requestAnimationFrame コールバックでスタイル変更を処理します。
長時間実行される入力ハンドラを避ける
最速のケースでは、ユーザーがページと対話するときに、ページのコンポジタ スレッドが、ユーザーのタッチ入力を感知し、単純にコンテンツを移動させることができます。これには、メインスレッドによる処理(JavaScript、レイアウト、スタイル、ペイントの実行)は必要ありません。
ただし、touchstart
、touchmove
、touchend
などの入力ハンドラをアタッチする場合は、これらのハンドラの実行の完了をコンポジタ スレッドが待機しなければなりません。これは、preventDefault()
が呼び出され、タッチ スクロールの実行が停止される場合があるためです。preventDefault()
が呼び出されない場合でも、コンポジタは待機する必要があり、これによりユーザーのスクロールがブロックされ、ぎこちない動きやフレームの欠損につながります。
つまり、実行するすべての入力ハンドラがすぐに実行され、コンポジタがジョブを実行できるようにする必要があります。
入力ハンドラでスタイルを変更しない
入力ハンドラ(スクロールやタップなど)は、requestAnimationFrame
コールバックの直前に実行されるようにスケジュール設定されます。
これらのハンドラのいずれかで視覚的な変更を加えると、requestAnimationFrame
の開始時に、スタイル変更が保留状態になります。その後、requestAnimationFrame コールバックの開始時に視覚的なプロパティを読み取ると、大きく複雑なレイアウトとレイアウト スラッシングの回避で説明しているとおり、強制同期レイアウトがトリガーされます。
スクロール ハンドラのデバウンス
上記の両方の問題の解決方法は同じです。常に次の 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);
これにより、入力ハンドラを軽量化できるという利点もあります。計算コストの高いコードのスクロールやタップなどをブロックしなくなるという利点もあります。