في حدث DOM للمتصفح ، سيتم تشغيل بعض الأحداث بشكل مستمر مع عمليات المستخدم. على سبيل المثال: تغيير حجم نافذة المتصفح ، وقم بتمرير صفحة المتصفح ، و Mousemove. وهذا يعني أنه عندما يقوم المستخدم بإعداد عمليات المتصفح هذه ، إذا كانت طريقة معالجة الأحداث المقابلة مرتبطة بالبرنامج النصي ، فسيتم تشغيل هذه الطريقة بشكل مستمر.
هذا ليس ما نريده ، لأنه في بعض الأحيان إذا كانت طريقة معالجة الأحداث كبيرة نسبيًا ، فإن عمليات DOM مثل المعقدة ، وتؤدي ذلك باستمرار إلى هذه الأحداث ، ستؤدي إلى خسائر في الأداء ، مما يؤدي إلى انخفاض في تجربة المستخدم (استجابة واجهة المستخدم البطيئة ، متصفح عالق ، إلخ). لذلك عادةً ما نضيف منطقًا إلى الحدث المقابل لتأخير التنفيذ.
بشكل عام ، نستخدم الكود التالي لتنفيذ هذه الوظيفة:
var count = 0 ؛ function testfn () {console.log (count ++) ؛ } // عندما يقوم المتصفح بتغيير حجم // 1. قم بمسح المؤقت السابق // 2. أضف مؤقتًا لتأخير الوظيفة الحقيقية testfn بمقدار 100 مللي ثانية لإعداد نافذة. ClearTimeout (مؤقت) ؛ timer = setTimeOut (function () {testfn () ؛} ، 100) ؛} ؛سيجد الطلاب الحذرون أن الكود أعلاه خاطئ بالفعل. هذه مشكلة ستجعلها المبتدئين: يجب حفظ قيمة الإرجاع لوظيفة SetTimeout في متغير عالمي نسبي ، وإلا سيتم إنشاء جهاز توقيت جديد في كل مرة يتم فيها تغيير حجم التغييرات ، والتي لن تحقق التأثير الذي نرسله.
لذلك قمنا بتعديل الكود:
var timer = null ؛ window.onresize = function () {clearTimeOut (timer) ؛ timer = setTimeOut (function () {testfn () ؛} ، 100) ؛} ؛في هذا الوقت ، يكون الرمز طبيعيًا ، ولكن هناك مشكلة جديدة أخرى - يتم إنشاء مؤقت متغير عالمي. هذا شيء لا نريد رؤيته. إذا كانت هذه الصفحة تحتوي على وظائف أخرى ، فإنها تسمى أيضًا Timer. الرموز المختلفة سوف تسبب تعارضات من قبل. لحل هذه المشكلة ، نحتاج إلى استخدام ميزة لغة JavaScript: إغلاق الإغلاق. يمكن للقراء التعرف على المعرفة ذات الصلة في MDN. الرمز المعدل كما يلي:
/*** طريقة اختناق الوظيفة* param وظيفة استدعاء تأخير الدالة* param تأخير المدة التي تستغرقها طريقة تأخير* return لتأخير التنفيذ*/var throttle = function (fn ، delay) {var timer = null ؛ Return Function () {cleartimeout (timer) ؛ timer = setTimeOut (function () {fn () ؛} ، delay) ؛ }} ؛ window.onresize = Throttle (testfn ، 200 ، 1000) ؛نستخدم وظيفة الإغلاق (خانق خانق) لوضع المؤقت داخليًا وإعادة وظيفة معالجة التأخير. وبهذه الطريقة ، يكون متغير المؤقت غير مرئي للخارج ، ولكن يمكن أيضًا الوصول إلى متغير المؤقت عند تشغيل وظيفة التأخير الداخلي.
بالطبع ، ليس من السهل على المبتدئين فهم المبتدئين. يمكننا تغيير طريقة الكتابة لفهم:
var throuttle = function (fn ، delay) {var timer = null ؛ Return Function () {cleartimeout (timer) ؛ timer = setTimeOut (function () {fn () ؛} ، delay) ؛ }} ؛ var f = throttle (testfn ، 200) ؛ window.onresize = function () {f () ؛} ؛فيما يلي وجهة نظر: الوظيفة التي يتم إرجاعها بواسطة الخانق بعد استدعاءها هي الوظيفة الحقيقية التي يجب استدعاؤها عند تشغيل onResize
الآن يبدو أن هذه الطريقة قريبة من الكمال ، ولكن هذا ليس هو الحال في الاستخدام الفعلي. على سبيل المثال:
إذا قام المستخدم بتغيير حجم نافذة المتصفح باستمرار ، فلن يتم تنفيذ وظيفة معالجة التأخير مرة واحدة
لذلك نحتاج إلى إضافة وظيفة أخرى: عندما يقوم المستخدم بتغيير حجمه ، يجب تشغيله مرة واحدة على الأقل خلال فترة زمنية معينة. نظرًا لأنه في غضون فترة زمنية معينة ، يمكن أن تستغرق شرط الحكم هذا الوقت الحالي مللي ثانية ، وستقوم كل استدعاء دالة بطرح الوقت الحالي من وقت الاتصال الأخير ، ثم يحكم على أنه إذا كان الفرق أكبر من فترة زمنية معينة ، فسيتم إرسالها مباشرة ، وإلا فإنها ستتبع منطق تأخير المهلة.
ما يجب الإشارة إليه في الكود التالي هو:
1. وظيفة المتغيرات السابقة تشبه وظيفة المؤقت. تم تسجيل كلاهما المعرف الأخير ويجب أن يكون متغيرات عالمية نسبية.
2. إذا كانت عملية المنطق تتبع المنطق "يتم تشغيله مرة واحدة على الأقل" ، فيجب إكمال استدعاء الوظيفة لإعادة ضبط الوقت السابق إلى الوقت الحالي. ببساطة ، هو: بالمقارنة مع آخر مرة ، فهي في الواقع هي التيار الحالي.
/*** طريقة اختناق الوظيفة* param function fn funct function function* param number تأخير كم من الوقت هو تأخير* param على الأقل كم من الوقت يتم تشغيله* طريقة وظيفة return لتأخير تنفيذ*/var throttle = function (fn ، delay ، على الأقل) {var timer = null ؛ var السابق = فارغ ؛ Return Function () {var now = +new Date () ؛ إذا (! السابق) السابق = الآن ؛ إذا (الآن - سابق> على الأقل) {fn () ؛ // إعادة تعيين وقت البدء الأخير حتى وقت الانتهاء من هذا الوقت السابق = الآن ؛ } آخر {cleartimeout (timer) ؛ timer = setTimeOut (function () {fn () ؛} ، delay) ؛ }}} ؛يمارس:
نحاكي مشهدًا من الاختناق عند تمرير نافذة ، أي عندما يقوم المستخدم بتمرير الصفحة لأسفل ، نحتاج إلى اختناق بعض الأساليب ، مثل: حساب موضع DOM ، وما إلى ذلك ، والذي يتطلب تشغيل عناصر DOM مستمرة.
الرمز الكامل كما يلي:
<! doctype html> <html lang = "en"> <head> <meta charset = "utf-8"> <title> Throttle </title> </head> <body> <div style = "height: 5000px"> <div id = "demo" style = "fump ؛" document.getElementById ('Demo') ؛ وظيفة testfn () {demo.innerhtml += 'testfn كان يسمى " +++ count +' time <br> '؛} var throttle = function (fn ، delay ، على الأقل) {var timer = null ؛ var السابق = فارغ ؛ Return Function () {var now = +new Date () ؛ إذا (! السابق) السابق = الآن ؛ if (على الأقل && الآن - سابق> على الأقل) {fn () ؛ // إعادة تعيين وقت البدء الأخير حتى وقت الانتهاء من هذا الوقت السابق = الآن ؛ ClearTimeout (مؤقت) ؛ } آخر {cleartimeout (timer) ؛ timer = setTimeOut (function () {fn () ؛ previce = null ؛} ، Delay) ؛ }}}} ؛ window.onscroll = خنق (testfn ، 200) ؛ // window.onscroll = Throttle (testfn ، 500 ، 1000) ؛ </script> </body> </html>نستخدم حالتين لاختبار التأثير ، وهما إضافة ما لا يقل عن تشغيل على الأقل على الأقل وليس إضافة:
// case 1window.onscroll = Throttle (testfn ، 200) ؛ // case 2window.onscroll = Throttle (testfn ، 200 ، 500) ؛
تتجلى الحالة 1 على النحو التالي: لن يتم استدعاء testfn أثناء عملية التمرير للصفحة (لا يمكن إيقافها) ، وسيتم استدعاؤها مرة واحدة حتى تتوقف ، مما يعني أنه يتم تنفيذ آخر وقت في الخانق ، ويتم التأثير كما هو موضح في الشكل (انظر صورة GIF الأصلية):
تتجلى الحالة 2 على النحو التالي: أثناء عملية التمرير للصفحة (لا يمكن إيقافها) ، سيتم تأخير TestFN بمقدار 500 مللي ثانية لأول مرة (من منطق التأخير على الأقل) ، ثم يتم تنفيذها على الأقل كل 500 مللي ثانية ، كما هو موضح في الشكل
حتى الآن ، تم الانتهاء من النتائج التي نريد تحقيقها بشكل أساسي. يمكن للقراء التفكير في بعض التحسينات المساعدة اللاحقة بأنفسهم ، مثل: وظيفة هذا الإشارة ، وتوفير قيمة الإرجاع ، إلخ.
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.