В событии Browser DOM некоторые события будут непрерывно запускаться с операциями пользователя. Например: измените размер окна браузера, прокрутите страницу браузера и MouseMove. То есть, когда пользователь запускает эти операции браузера, если соответствующий метод обработки событий связан с скриптом, этот метод будет запущен непрерывно.
Это не то, что мы хотим, потому что иногда, если метод обработки событий является относительно большим, операции DOM, такие как комплексные, и постоянно вызывая такие события, вызовут потери производительности, что приведет к снижению пользовательского опыта (медленный ответ пользовательского интерфейса, браузер застрял и т. Д.). Таким образом, обычно мы добавляем логику в соответствующее событие, чтобы задержать выполнение.
Вообще говоря, мы используем следующий код для реализации этой функции:
var count = 0; function testfn () {console.log (count ++); } // Когда браузер изменяется // 1. Очистить предыдущий таймер // 2. Добавить таймер, чтобы отложить реальную функцию TestFN на 100 миллисекунд в Trigger Window.onresize = function () {var Timer = null; ClearTimeout (таймер); timer = settimeout (function () {testfn ();}, 100);};Осторожные студенты обнаружили, что приведенный выше код на самом деле неверен. Это проблема, которую будут создавать новички: возвращаемое значение функции Settimeout должно быть сохранено в относительной глобальной переменной, в противном случае новый таймер будет генерироваться каждый раз, когда изменяется размер, что не будет достигать эффекта, который мы отправляем.
Итак, мы изменили код:
var -timer = null; window.onresize = function () {cleartimeout (timer); timer = settimeout (function () {testfn ();}, 100);};В настоящее время код нормальный, но есть еще одна новая проблема - генерируется глобальный таймер переменной. Это то, что мы не хотим видеть. Если на этой странице есть другие функции, она также называется таймером. Различные коды будут вызывать конфликты раньше. Чтобы решить эту проблему, нам нужно использовать языковую функцию JavaScript: закрытие закрытия. Читатели могут узнать о связанных знаниях в MDN. Модифицированный код заключается в следующем:
/*** Метод дроссельной функции функции* @param Функция fn задержка Функция вызова* @param Номер задержка Какова длина метод задержки* @return для задержки выполнения*/var throttle = function (fn, задержка) {var timer = null; return function () {cleartimeout (timer); timer = settimeout (function () {fn ();}, задержка); }}; window.onresize = дроссель (testfn, 200, 1000);Мы используем функцию закрытия (дроссельная заслонка), чтобы поместить таймер внутренне и возвращать функцию обработки задержки. Таким образом, переменная таймера невидима снаружи, но переменная таймера также можно получить, когда запускается функция внутренней задержки.
Конечно, этот метод письма нелегко понять новичкам. Мы можем изменить метод написания, чтобы понять:
var Throttle = function (fn, Delay) {var timer = null; return function () {cleartimeout (timer); timer = settimeout (function () {fn ();}, задержка); }}; var f = throttle (testfn, 200); window.onresize = function () {f ();};Вот точка зрения: функция, возвращаемая дроссельной заслонкой после вызванной, является реальной функцией, которую необходимо вызвать, когда запускается OnResize
Теперь кажется, что этот метод близок к совершенству, но это не так в реальном использовании. Например:
Если пользователь постоянно изменяет размер размера окна браузера, функция обработки задержки не будет выполнена один раз
Таким образом, нам нужно добавить еще одну функцию: когда пользователь запускает размер, это должно быть вызвано хотя бы один раз в течение определенного периода времени. Поскольку это в течение определенного периода времени, это условие суждения может занять текущее время миллисекунды, и каждая функция вызывает вызывает текущее время из последнего времени вызова, а затем судьи, если разница больше, чем определенный период времени, она будет отправлена непосредственно, в противном случае она все равно будет следовать логике задержки времени ожидания.
Что нужно указать в следующем коде:
1. Функция предыдущих переменных аналогична функции таймера. Они оба записаны последним идентификатором и должны быть относительными глобальными переменными.
2. Если логический процесс следует за логикой «запускается по крайней мере один раз», то функциональный вызов должен быть завершен для сброса до текущего времени. Проще говоря, это: по сравнению со следующим в последнее время, это фактически текущий.
/*** Метод дроссельной функции функции* @param Функция Fn Функция вызова задержки* @param Номер задержка Какова длина задержка* @param, по крайней мере, как долго он запускается* @return Function Метод для задержки выполнения*/var throttle = function (fn, задержка, по крайней мере) {var timer = null; var предыдущий = null; return function () {var now = +new Date (); if (! предыдущий) предыдущий = сейчас; if (теперь - предыдущий> по крайней мере) {fn (); // сбросить последнее время начала до конца времени этого времени предыдущее = сейчас; } else {cleartimeout (timer); timer = settimeout (function () {fn ();}, задержка); }}};упражняться:
Мы имитируем сцену дросселирования при прокручивании окон, то есть, когда пользователь прокручивает страницу вниз, нам необходимо дросселивать некоторые методы, такие как: расчет положения DOM и т. Д., Который требует непрерывной работы элементов DOM.
Полный код заключается в следующем:
<! Doctype html> <html lang = "en"> <head> <meta charset = "UTF-8"> <Title> Throttle </title> </head> <body> <div Style = "Высота: 5000px"> <div id = "demo" style = "position:"> </div> </div> <crovipt> var var varce = 0, demo = ". document.getElementbyId ('demo'); function testfn () {demo.innerhtml += 'testfn назывался' +++ count +'time <br>';} var throttle = function (fn, задержка, по крайней мере) {var timer = null; var предыдущий = null; return function () {var now = +new Date (); if (! предыдущий) предыдущий = сейчас; if (по крайней мере && сейчас - предыдущий>, по крайней мере,) {fn (); // сбросить последнее время начала до конца времени этого времени предыдущее = сейчас; ClearTimeout (таймер); } else {cleartimeout (timer); timer = settimeout (function () {fn (); предыдущий = null;}, задержка); }}}}; window.onscroll = дроссель (testfn, 200); // window.onscroll = дроссель (testfn, 500, 1000); </script> </body> </html>Мы используем два случая для проверки эффекта, а именно, добавляя хотя бы запуск, по крайней мере, по крайней мере и не добавляя:
// case 1window.onscroll = дроссель (testfn, 200); // case 2window.onscroll = дроссель (testfn, 200, 500);
Случай 1 проявляется как: testfn не будет вызван во время процесса прокрутки страницы (не может быть остановлен), и его будет вызвано один раз, пока он не остановится, что означает, что последнее время Settimeout в дроссельной заслоке выполняется, и эффект, как показано на рисунке (см. Исходное изображение GIF)::
Случай 2 проявляется как: во время процесса прокрутки страницы (не может быть остановлен), TestFN будет задерживаться на 500 мс впервые (по крайней мере из логики задержки), а затем выполнять, по крайней мере, каждые 500 мс, эффект показан на рисунке
До сих пор результаты, которые мы хотим достичь, были в основном завершены. Читатели могут подумать о некоторых последующих вспомогательных оптимизациях сами по себе, например: функционировать это указание, сохранение возврата и т. Д.
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.