Форматирование html после fetch запроса
Использую fetch запрос для обновления информации в блоке страницы (загружаются карточки предложений после фильтрации).
Некоторые нюансы:
- Карточки расположены внутри контейнера div#cards
- Карточки выстраиваются в masonry layout с помощью JS-библиотеки
- fetch передает готовую вёрстку всего содержимого для div#cards
- fetch вызывается изменением любого фильтра и отдаёт новую вёрстку (обработка происходит на сервере в PHP)
- Контент заменяется в div#cards с помощью inner.html
Все работает хорошо, кроме одного нюанса. Скрипт, выстраивающий сетку, не дожидается обновления всего контента в div и запускается раньше, из-за чего нарушается порядок блоков и отображение.
Проверено: установка timeout для скрипта решает проблему, но существует задержка, в ходе которой посетитель видет «сырой» контент без masonry.
Что пробовал делать:
- Вызывал скрипт в fetch через then, сразу после передачи inner.html
- Вызывал скрипт отдельно, после исполнения fetch
- Пытался использовать отслеживание события мутации div, прослушивание не исправило ситуацию
- Ставил timeout - помогает, но из-за задержки вёрстка выглядит пару секунд ужасно
Вопрос: возможно ли как-то запустить сборку макета (скрипт) ровно в тот момент, когда контент будет заменен на 100%?
Возможно, есть идеи, куда копать или как по-другому решить вопрос? Благодарю.
Ответы (1 шт):
Проблема, с которой вы сталкиваетесь, связана с асинхронной природой выполнения операций в браузере. Когда вы обновляете содержимое div#cards
с помощью innerHTML, новый контент ещё не полностью отрисован, и скрипт, отвечающий за выстраивание сетки (например, Masonry), начинает работу раньше, чем блоки фактически отображены.
Одним из способов решения этой проблемы является использование события load на изображениях, которые содержатся в карточках предложений. Когда все изображения полностью загружены, вы можете вызвать скрипт, отвечающий за выстраивание сетки.
Чисто в теории этот код может помочь вам оптимизировать своё решение. Дайте мне знать если это поможет
function loadMasonryLayout() {
// Код для выстраивания сетки (например, вызов Masonry)
// ...
}
function updateContent(html) {
var cardsContainer = document.getElementById("cards");
cardsContainer.innerHTML = html;
var images = cardsContainer.getElementsByTagName("img");
var imagesLoaded = 0;
function imageLoadHandler() {
imagesLoaded++;
if (imagesLoaded === images.length) {
loadMasonryLayout();
}
}
for (var i = 0; i < images.length; i++) {
images[i].addEventListener("load", imageLoadHandler);
}
}
function fetchContent() {
fetch(url)
.then(function(response) {
return response.text();
})
.then(function(data) {
updateContent(data);
})
.catch(function(error) {
console.error("Error:", error);
});
}
// Вызываем функцию fetchContent при изменении фильтра
// или в любом другом месте, где нужно обновить контент
fetchContent();