ブラウザDOMイベントでは、一部のイベントはユーザーの操作で継続的にトリガーされます。たとえば、ブラウザウィンドウのサイズを変更し、ブラウザページをスクロールし、MouseMoveを使用します。つまり、ユーザーがこれらのブラウザ操作をトリガーすると、対応するイベント処理方法がスクリプトにバインドされている場合、この方法は継続的にトリガーされます。
これは私たちが望むものではありません。なぜなら、イベント処理方法が比較的大きく、複雑なDOM操作が複雑であり、そのようなイベントを絶えずトリガーするとパフォーマンスの損失を引き起こし、ユーザーエクスペリエンス(UI応答の遅い、ブラウザがスタックするなど)が低下するからです。そのため、通常、対応するイベントにロジックを追加して、実行を遅らせます。
一般的に言えば、次のコードを使用してこの関数を実装します。
var count = 0; function testfn(){console.log(count ++); } //ブラウザが// 1./ 1。前のタイマーをクリアするとき// 2。タイマーを追加して、window.onresize = function(){var timer = null; ClearTimeout(タイマー); Timer = setimeout(function(){testfn();}、100);};慎重な学生は、上記のコードが実際に間違っていることに気付くでしょう。これは初心者が発生させる問題です。SettimeOut関数の返品値は相対的なグローバル変数に保存する必要があります。そうしないと、サイズが変更されるたびに新しいタイマーが生成されます。
そこで、コードを変更しました。
var timer = null; window.onresize = function(){cleartimeout(Timer); Timer = setimeout(function(){testfn();}、100);};現時点では、コードは正常ですが、別の新しい問題があります - グローバル変数タイマーが生成されます。これは私たちが見たくないものです。このページに他の機能がある場合、タイマーとも呼ばれます。異なるコードは、以前に競合を引き起こします。この問題を解決するには、JavaScript:閉鎖の言語機能を使用する必要があります。読者は、MDNの関連知識について学ぶことができます。変更されたコードは次のとおりです。
/***関数スロットリング方法* @param関数fn遅延function* @param number delay delay* @return function execution*/var throttle = function(fn、delay){var timer = null; return function(){cleartimeout(タイマー); Timer = setimeout(function(){fn();}、delay); }}; window.onresize = throttle(testfn、200、1000);閉鎖関数(スロットルスロットリング)を使用して、タイマーを内部に配置し、遅延処理機能を返します。これにより、タイマー変数は外側には見えませんが、内部遅延関数がトリガーされたときにタイマー変数にアクセスすることもできます。
もちろん、この執筆方法は、初心者にとって簡単ではありません。執筆方法を変更して理解できます。
var throttle = function(fn、delay){var timer = null; return function(){cleartimeout(タイマー); Timer = setimeout(function(){fn();}、delay); }}; var f = throttle(testfn、200); window.onresize = function(){f();};視点は次のとおりです。スロットルによって返された関数は、onRysizeがトリガーされたときに呼び出される必要がある実際の関数です
今では、この方法は完璧に近いようですが、実際に使用する場合はそうではありません。例えば:
ユーザーがブラウザのウィンドウサイズを常に変更している場合、遅延処理機能は1回実行されません
したがって、別の関数を追加する必要があります。ユーザーがサイズをトリガーする場合、特定の期間内に少なくとも1回トリガーする必要があります。一定期間内であるため、この判断条件は現在のミリ秒をかけることができ、各関数は最後の呼び出し時間から現在の時間を減算し、差が一定期間よりも大きい場合は直接送信されると判断します。
次のコードで指摘する必要があるのは次のとおりです。
1.以前の変数の関数は、タイマーの関数に似ています。どちらも最後の識別子に記録されており、相対的なグローバル変数でなければなりません。
2.ロジックプロセスが「少なくとも1回はトリガーされる」ロジックに従う場合、現在の時刻をリセットするために関数呼び出しを完了する必要があります。簡単に言えば、それは次のとおりです。次の前回と比較して、実際には現在のものです。
/*** function trottling method* @param関数fn遅延コール関数* @param番号遅延*遅延* @param number少なくともトリガー* @return function execution*/var throttle = function(fn、delay、少なくとも){var timer = null; var forter = null; return function(){var now = +new date(); if(!前)以前= now; if(現在 - 前>少なくとも){fn(); //最終開始時間を今回の終了時刻までリセットしますprever = now; } else {cleartimeout(タイマー); Timer = setimeout(function(){fn();}、delay); }}};練習する:
ウィンドウがスクロールしたときにスロットリングのシーンをシミュレートします。つまり、ユーザーがページを下にスクロールするとき、DOM位置の計算など、DOM要素の継続的な動作など、いくつかの方法をスロットする必要があります。
完全なコードは次のとおりです。
<!doctype html> <html lang = "en"> <head> <meta charset = "utf-8"> <title> throttle </title> </head> <body> <body> <div style = "height:5000px"> <div id = "demo" style = "position:sixed;"> </div> <crupt> var count> var count = 0 function testfn(){demo.innerhtml += 'testfnは' +++ count +'time <br>';} var throttle = function(fn、delay、少なくとも){var timer = null; var forter = null; return function(){var now = +new date(); if(!前)以前= now; if(少なくとも&&今 - 以前>少なくとも){fn(); //最終開始時間を今回の終了時刻までリセットしますprever = now; ClearTimeout(タイマー); } else {cleartimeout(タイマー); Timer = setimeout(function(){fn();前= null;}、delay); }}}}; window.onscroll = throttle(testfn、200); // window.onscroll = throttle(testfn、500、1000); </script> </body> </html>2つのケースを使用して効果をテストします。つまり、少なくとも少なくともトリガーを追加して追加し、追加しません。
// case 1window.onscroll = strottle(testfn、200); // case 2window.onscroll = throttle(testfn、200、500);
ケース1は次のように表示されます。TESTFNはページスクロールプロセス中に呼び出されず(停止できません)、停止するまで一度呼び出されます。
ケース2は次のように表示されます。ページスクロールプロセス(停止できない)では、testFNは初めて500ms遅延し(少なくとも遅延ロジックから)、少なくとも500msごとに実行されると、図に示すように効果が示されています。
これまでのところ、達成したい結果は基本的に完了しています。読者は、次のような機能、返品価値の節約など、その後の補助最適化について考えることができます。
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。