Как подгружать страницы без перезагрузки на чистом js с прогрессом?
Здравствуйте. Хочу сделать возможность загружать страницы без перезагрузки и чтобы можно было посмотреть прогресс загрузки этой страницы.
Делаю кнопку: <button onclick="send(event, 'req.html')">Загрузить</button> И вот такую функцию: function send(event, html){ console.log("Отправка запроса"); event.preventDefault ? event.preventDefault() : event.returnValue = false; var req = new XMLHttpRequest(); req.open('POST', html, true); req.onload = function() { if (req.status >= 200 && req.status < 400) { document.querySelector(".result").insertAdjacentHTML("afterbegin", this.response); } else {alert("Ошибка сервера. Номер: "+req.status);}}; req.onerror = function() {alert("Ошибка отправки запроса");}; req.send(); } Проблема в том, что req.onprogress отрабатывает только на запрос, а не на содержимое документа. Ведь запрос возвращает мне только текст того документа, а в тексте находятся изображения. Грубо говоря страница req.html выглядит так: <img src="big1.png" alt=""> <img src="big2.png" alt=""> <img src="big3.png" alt=""> Как можно повесить прогресс на всю страницу из запроса? Ещё раз повторюсь: весь документ req.html с учётом изображений весит 9мб, а текст документа (что я как раз и получаю) весит несколько килобайт. Прогресс разумеется сразу будет 100% потому что я загружаю лишь килобайты. Как загрузить именно весь документы и получить прогресс загрузки? Сам этот нативный ajax я брала на просторах форумов. Мне кажется, что там можно что-то изменить и тогда я буду получать именно содержимое документа с объектами в нём, а не просто текст. |
Событие загрузки документа обрабатывают или его компонентов, в данном случае изображений. А "что там можно что-то изменить и тогда я буду получать именно содержимое документа", это где, в самом ответе? Ну можете не подгружать картинки, а вставить в src их base64, вот только документ ваш при этом будет 27 МБ весить.
|
laimas,
С чего вы взяли, что размер страницы будет 27мб? Но это не важно, потому что это не вариант. Я просто представляю это так: идёт запрос > получаем документ > загружаем его в памяти > как только загрузился - отображаем. Пока грузим в памяти - отображаем прогресс. Просто есть https://github.com/HubSpot/pace , который отображает прогресс бар просто для страницы. Наверняка можно как-то сделать и для подгружаемой страницы. |
Цитата:
Установите обработчик загрузки изображений и отрисовывайте прогресс. PS. Ну или обрабатывайте как ранее говорилось, событие window onload, рисуя "аля прогресс", как это делается в сети есть, одним словом просто фикция. |
laimas,
я не нашла в сети XMLHttpRequest и onload изображений |
XMLHttpRequest имеет прогресс и его событие никак не связано с событием загрузки изображений. Изображения браузер закачивает через шлюз, и его событие загрузки сообщает о загруженном изображении, но никак не сможет вам сообщить на сколько процентов оно загружено. Собственно и прогресс имеющийся не только у XMLHttpRequest никогда вам не отобразит выполнение от 0 до 100% с шагом 1%.
Получили ответ сервера, пусть это будет 10% от объема, отобразили их, далее обрабатываете загрузку коллекции изображений, добавляя к прогрессу при загрузке каждого проценты зависящие, например, от размера изображения. |
А о примерах в сети, я имел ввиду фикцию прогресса загрузки страницы, то есть события window.onload.
|
laimas,
Допустим. Как в моём случае использовать onload? Куда мне его вешать, чтобы при получении результата и полной его загрузки отрабатывал какой-нибудь console.log("готово")? Я пыталась повесить onload на div в index.html , и onload в подгружаемом элементе - всё безуспешно. |
Вы же сами определили сценарий - загрузка асинхронная, где малая часть текст, большая часть картинки.
Определили свой, пользовательский, прогресс, "плавность шага" которого пусть будет обеспечиваться css (найдете в сети, есть такое и готовое). Пусть малая часть, это 10%, остальные 90%, это картинки, и пусть их будет 9. Сервер ответил, отмечаете на своем прогрессе 10%, далее обрабатываете событие image.onload этих изображений добавляя по каждому этому событию либо по 90/9%, либо проценты определяют размеры изображений, тогда 90%, это 100% размера всех изображений. А как обрабатывается, это можно посмотреть, найдите в сети "предварительная загрузка изображений, прелоадер и т.п.", и выбирайте вам подходящее. |
<style> * { padding: 0; margin: 0; background-color: rgb(255, 237, 213); } .progress-bar { width: 100%; height: 5px; box-sizing: border-box; } .progress-bar-meter { background-color: red; width: 0%; height: inherit; transition: width .5s; } .lazy-images { width: 24%; } .images { text-align: center; } </style> <div class="progress-bar"> <div class="progress-bar-meter"></div> </div> <div class="images"> <img src="https://cdn.pixabay.com/photo/2020/07/10/22/38/cows-5392356_1280.jpg" class="lazy-images" alt="me" /> <img src="https://cdn.pixabay.com/photo/2020/07/02/08/00/landscape-5362157_1280.jpg" class="lazy-images" alt="me" /> <img src="https://cdn.pixabay.com/photo/2020/07/08/05/31/gray-cat-5382617_1280.jpg" class="lazy-images" alt="me" /> <img src="https://cdn.pixabay.com/photo/2020/07/02/17/29/landscape-5363681_1280.jpg" class="lazy-images" alt="me" /> </div> <script> function LazyLoader({ queryImages, queryProgress }) { let progressLoad = 0; const lazyImages = document.querySelectorAll(queryImages) const progressBarMeter = document.querySelector(queryProgress) const updateProgressBar = () => progressBarMeter.style.width = `${100 / (lazyImages.length / ++progressLoad) || 0}%` lazyImages.forEach( lazyImage => // lazyImage.naturalWidth > 0 - т.е. уже в кэше lazyImage.naturalWidth > 0 ? updateProgressBar() : new Promise((resolve, reject) => lazyImage.onload = () => resolve(updateProgressBar())) ) } document.addEventListener('DOMContentLoaded', function () { new LazyLoader({ queryImages: 'img.lazy-images', queryProgress: '.progress-bar-meter' }) }); </script> |
Часовой пояс GMT +3, время: 15:53. |