предисловие
Front-end разработка будет сталкиваться с некоторыми частыми триггерами событий, такими как: прокрутка окна, изменение размера, mousedown, mousemove, keyup, keydown и т. д. Если вы ничего не сделаете со своим кодом, вы обнаружите, что страница зависает и срабатывает интерфейсные запросы и другие проблемы, в этой статье будет проанализирована реализация функции троттлинга и анти-шейка, и постепенно шаг за шагом будет раскрыто истинное лицо функции троттлинга и анти-шейка💜
концепция
Поймите принцип триггера анти-дрожания и дросселирования и разумно используйте его в соответствии с различными сценариями использования.
Функция debounce (дебаунс)
当调用动作过n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间,不会执行
Поймите принцип:
Несмотря на то, что событие запускается, оно должно быть выполнено через n секунд после запуска события.Если событие запускается снова в течение n секунд после запуска события, время нового события имеет преимущественную силу, и оно будет выполнено через n секунд Короче говоря, необходимо, чтобы Он не выполнялся до тех пор, пока событие больше не будет срабатывать в течение n секунд после срабатывания события!
функция дроссельной заслонки
预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期
Поймите принцип:
Функция гарантированно будет выполнена один раз за указанное время
выполнить
Стабилизатор
В соответствии с принципом защиты от сотрясений код реализации выглядит следующим образом, и следующие примеры будут использоваться регулярно:
# 箭头log函数
let count = 0
const log = () => {
console.log(this)
++count
console.log(count)
}
# 函数表达式
const log = function (evt) {
console.log(this)
console.log(evt)
++count
console.log(count)
}
const debounce = function (fn, delay){
let timeout = null
return function () {
if (timeout) {
clearTimeout(timeout)
}
timeout = setTimeout(fn, delay)
}
}
Возьмем в качестве примера частые клики.
Обычное использование: meContain.onclick = debounce(log, 1000)
react demo: ...onClick={debounce(log.bind(this), 1000)}
Вы, ребята, обнаружили, что функция защиты от сотрясений все еще несовершенна?
- это указывает на объект события
- Если пользователь продолжает нажимать кнопку отправки сейчас, запрос не будет отправлен и не будет выдано приглашение, что очень плохо для пользователя.
это указывает на объект события
это указывает на
- В функции журнала console.log(this), когда функция debounce не используется, значение this равно: undefined, это связано с тем, что используется функция стрелки, и когда вызывается onClick, bind(this), this указывает на пример компонента реакции
- При обычном использовании console.log(this), когда функция устранения дребезга не используется, значение this равно:
<div id="mecontain"></div>
объект события
- Без функции debouce объект ClickEvent будет напечатан
- В функции debounce он печатает только undefined
Чтобы решить вышеуказанные проблемы, изменить наш код
const debounce = function (fn, delay){
let timeout = null
return function () {
const context = this;
const args = arguments;
clearTimeout(timeout)
timeout = setTimeout(() => {
fn.apply(context, args)
}, delay)
}
}
Интерактивный опыт оптимизации
Если вы хотите выполнить функцию один раз, вам не нужно ждать, пока событие перестанет запускаться, прежде чем выполнять ее, а затем ждать n секунд после того, как событие перестанет запускаться, после чего вы можете повторно запустить выполнение.
Определите, следует ли выполнять немедленно, добавив isImmeDiate
const debounce = function (fn, delay,isImmeDiate= false){
let timeout = null
return function () {
const context = this;
const args = arguments;
if(timeout) clearTimeout(timeout)
if(isImmeDiate) {
# 判断是否已经执行过,不要重复执行
let callNow = !timeout
timeout = setTimeout(function(){
timeout = null;
}, delay)
if(callNow) result = fn.apply(context, args)
} else {
timeout = setTimeout(() => {
fn.apply(context, args)
}, delay)
}
return result
}
}
Если вы хотите добавить переключатель отмены дребезга, просто добавьте функцию отмены, чтобы очистить тайм-аут таймера = null
const debounce = function (fn, delay,isImmeDiate= false){
let timeout = null
const debounced = function () {
const context = this;
const args = arguments;
if(timeout) clearTimeout(timeout)
if(isImmeDiate) {
# 判断是否已经执行过,不要重复执行
# setTimeout也是一直在更新的
let callNow = !timeout
timeout = setTimeout(function(){
timeout = null;
}, delay)
if(callNow) result = fn.apply(context, args)
} else {
timeout = setTimeout(() => {
fn.apply(context, args)
}, delay)
}
return result
}
debounced.prototype.cancle = function() {
clearTimeout(timeout)
timeout = null
}
return debounced
}
Здесь мы реализовали функцию стабилизации, но у маленьких друзей нет другого представления об этом?
дросселирование
В соответствии с принципом дросселирования код реализации выглядит следующим образом, и следующие примеры будут использоваться регулярно:
Реализация метки времени
const throttle = function (fn, delay) {
let preTime = 0;
return function () {
const context = this;
const args = arguments;
const now = +new Date();
if (now - preTime > delay) {
fn.apply(context, args);
preTime = now;
}
}
}
Реализация таймера
const throttle = function (fn, delay) {
let timeout = null
return function () {
const context = this;
const args = arguments;
if (!timeout) {
timeout = setTimeout(function(){
timeout = null
fn.apply(context, args)
}, delay)
}
}
}
# 如果需要立刻执行,其实变更下执行顺序即可
timeout = setTimeout(function(){
timeout = null
//fn.apply(context, args)
}, delay)
fn.apply(context, args)
Также используйте частые клики в качестве примера.
Регулярное использование: meContain.onclick = дроссель (лог, 1000)
Вы нашли характеристики функции дросселирования на данный момент?
- Временная метка будет выполнена немедленно, таймер будет выполнен в первый раз через n секунд
- После того, как временная метка перестанет срабатывать, повторно выполнить событие невозможно.После того как таймер перестанет срабатывать, событие все равно будет выполнено снова.
Объедините две функции
const throttle = function (fn, delay) {
let timeout = null
let preTime = 0;
const later = function() {
preTime = +new Date()
timeout = null
fn.apply(context, args);
}
const throttled = function () {
const context = this;
const args = arguments;
const now = +new Date();
#下次触发fn剩余的时间
const remaining = delay - ( now - preTime)
#如果没有剩余的时间了或者系统时间变更
if (remaining <= 0 || remaining > delay) {
if(timeout) {
clearTimeout(timeout)
timeout = null
}
preTime = now
fn.apply(context, args);
} else if (!timeout) {
timeout = setTimeout(later, remaining)
}
}
throttled.cancel = function() {
clearTimeout(timeout);
previous = 0;
timeout = null;
}
return throttled
}
Суммировать
При троттлинге функция гарантированно выполняется однократно в течение заданного времени, при подавлении сотрясения, когда событие срабатывает непрерывно, функция обработки события будет выполняться только один раз, если событие не будет срабатывать повторно в течение определенного периода времени. наступает установленное время, оно будет выполнено снова. Когда событие срабатывает, задержка начинается снова.
Документация
Говоря о функции анти-встряски
регулирование функции
Функция защиты от тряски
регулирование функции
Саморекомендация
Углубитесь в исходный код, чтобы понять обработку ошибок Vue.
Webpack DllPlugin делает скорость сборки гладкой и шелковистой