У меня есть сценарий, который я считаю немного сложным: я хочу запланировать свои изменения в DOM, используя requestAnimationFrame (rAF)
, но у меня есть много условных c logi, которые я должен учитывать .
Рассмотрим это:
function writeToDOM(cb) {
fastdom.mutate(cb);
}
function performLogicThatDoesntUpdateTheDOM() {
// stuff I need to do with each touchmove event
// these things don't update the DOM, but they need to run
// after checking if the DOM needs to be updated
}
document.body.addEventListener('touchmove', event => {
if (propertyHasChanged) {
writeToDOM(function() {
someNode.classList.add('changed');
});
}
performLogicThatDoesntUpdateTheDOM();
if (anotherPropertyHasChanged) {
writeToDOM(function() {
anotherNode.classList.add('changed-too');
});
}
});
Идея состоит в том, что у меня есть функция-оболочка (writeToDOM
), которая принимает обратный вызов и ставит в очередь этот обратный вызов для выполнения в следующем доступном requestAnimationFrame, используя библиотека fastdom .
Событие touchmove
может запускаться несколько раз в кадре, поэтому я хочу убедиться, что я только обновляю DOM внутри rAF, хотя Любые другие необходимые вычисления я выполняю каждый раз при запуске обработчика touchmove. Проблема с вышеуказанным подходом заключается в том, что он по-прежнему планирует обновления DOM каждый раз, когда запускается обработчик touchmove, поэтому rAF в конечном итоге перегружается дублированными вызовами.
Я уже пробовал что-то вроде этого:
let writesAreScheduled = false;
document.body.addEventListener('touchmove', event => {
if (writesAreScheduled) {
// don't do anything
return;
}
if (propertyHasChanged) {
writeToDOM(function() {
writesAreScheduled = false;
someNode.classList.add('changed');
});
writesAreScheduled = true;
}
performLogicThatDoesntUpdateTheDOM();
if (anotherPropertyHasChanged) {
writeToDOM(function() {
writesAreScheduled = false;
anotherNode.classList.add('changed-too');
});
writesAreScheduled = true;
}
});
Проблема с этим подходом в том, что он не позволяет мне запускать performLogicThatDoesntUpdateTheDOM
после того, как запланировано обновление.
Итак, как я могу ограничить только обновления DOM, но всегда запускать другие мои logi c? Я не хочу ограничивать весь обработчик touchmove, только ту часть, которая обновляет DOM. У меня есть идея сделать что-то вроде этого:
let writesAreScheduled = false;
document.body.addEventListener('touchmove', event => {
const taskQueue = [];
if (propertyHasChanged) {
taskQueue.push(function() {
writesAreScheduled = false;
someNode.classList.add('changed');
});
}
performLogicThatDoesntUpdateTheDOM();
if (anotherPropertyHasChanged) {
taskQueue.push(function() {
writesAreScheduled = false;
anotherNode.classList.add('changed-too');
});
}
// only schedule DOM updates if none are currently scheduled
if (!writesAreScheduled) {
taskQueue.forEach(task => writeToDOM(task));
writesAreScheduled = true;
}
});
По сути, я храню массив обновлений DOM, которые необходимо выполнить, как только я определю, что они должны произойти. Затем, после выполнения всех определений, я проверяю флаг, чтобы увидеть, есть ли уже запланированный rAF, чтобы убедиться, что я планирую только один за раз. Помните, что моя цель - ограничить только частоту обновлений DOM, но запускать другие logi c так же часто, как срабатывает событие touchmove.
Я еще не реализовал это, и фактический код я Я работаю, это намного сложнее, поэтому мне не удалось создать более простую копию. У кого-нибудь есть другое / лучшее представление о том, как это сделать? Спасибо!