Как менять контент не перезагружая всю страницу
Перейти к содержимому

Как менять контент не перезагружая всю страницу

  • автор:

Как ставить пустые ссылки

Пустые ссылки делают, когда страницы ещё нет, а ссылка на неё уже есть. Например, в меню может быть ссылка на каталог, который ещё не начали верстать. Второй случай использования — когда нужно что-то показать на странице, но без перезагрузки страницы. Например, при создании модальных окон.

Есть несколько способов указывать пустые ссылки. Рассмотрим, чем грозит использование того или иного способа.

Один из самых худших вариантов, так как полностью перезагружает страницу. Скорее всего, с целью борьбы с ним и были созданы остальные способы создания пустых ссылок.

Изменяет адрес страницы, добавляет в конце #. Если было htmlacademy.ru, то после клика станет htmlacademy.ru/#. Прокручивает страницу к самому верху сайта. Если ссылка была в футере, то сайт прокрутится до самого начала. Это не всегда желательное поведение, поэтому этот вариант тоже отбросим.

Эта версия лучше, чем предыдущий способ, так как страница не прокручивается вверх. При этом меняется адрес страницы, а также добавляется # в конце адреса. Этот способ работает не во всех браузерах, поэтому есть следующий.

Можно сделать полноценную якорную ссылку, но при этом без элементов с id=»noscroll» . Этот способ работает во всех браузерах, не скроллит страницу к началу, но меняет ссылку, добавляя #noscroll в конец адреса.

Достаточно старый способ, который благодаря JavaScript буквально просит ссылку ничего не делать. Правильнее было бы написать javascript: undefined; , но этот вариант длиннее, поэтому придумали более короткую замену void (0) , который также возвращает undefined . Этот вариант был создан ещё в то время, когда JavaScript инлайнили в разметку. Ссылка в этом случае никуда не прокручивается, что лучше, чем в предыдущем варианте. Сам же метод позволял создать AJAX-запрос без перезагрузки страницы. Например, при открытии попапа делается запрос у сервера на его контент, затем попап открывается, и отрисовывается полученный контент от сервера.

На самом деле, когда программистам нечем заняться, они начинают придумывать новые способы. Просто потому что они могут. В этом методе ничто никуда не прокручивается и не прыгает. В href можно добавить что угодно, а в JavaScript не добавлять новый onclick . Хотя раньше это было важно. Сейчас новое событие можно добавить с помощью addEventListener .

В новой спецификации разрешили вообще не указывать href , если он не нужен. Ссылка как будто превращается в : удаляется стандартное подчёркивание снизу и синий цвет, указанный по умолчанию. С такой ссылки удаляются состояния: active, focus, так как с ней нельзя взаимодействовать. Это очень хорошо, так как ссылки, действительно, пока нет. Но при этом пользовательская стилизация, которую пишете вы, продолжает работать. В целом, можно сказать, что это самый ленивый и правильный вариант, однако он не всем подходит.

Определите, с какой целью вам нужно использовать пустые ссылки и изучите все преимущества и недостатки каждого метода. Только после этого вы сможете грамотно и корректно написать код.

«Доктайп» — журнал о фронтенде. Читайте, слушайте и учитесь с нами.

Страница: DOMContentLoaded, load, beforeunload, unload

У жизненного цикла HTML-страницы есть три важных события:

  • DOMContentLoaded – браузер полностью загрузил HTML, было построено DOM-дерево, но внешние ресурсы, такие как картинки и стили, могут быть ещё не загружены.
  • load – браузер загрузил HTML и внешние ресурсы (картинки, стили и т.д.).
  • beforeunload/unload – пользователь покидает страницу.

Каждое из этих событий может быть полезно:

  • Событие DOMContentLoaded – DOM готов, так что обработчик может искать DOM-узлы и инициализировать интерфейс.
  • Событие load – внешние ресурсы были загружены, стили применены, размеры картинок известны и т.д.
  • Событие beforeunload – пользователь покидает страницу. Мы можем проверить, сохранил ли он изменения и спросить, на самом ли деле он хочет уйти.
  • unload – пользователь почти ушёл, но мы всё ещё можем запустить некоторые операции, например, отправить статистику.

Давайте рассмотрим эти события подробнее.

DOMContentLoaded

Событие DOMContentLoaded срабатывает на объекте document .

Мы должны использовать addEventListener , чтобы поймать его:

document.addEventListener("DOMContentLoaded", ready); // не "document.onDOMContentLoaded = . "
  

В этом примере обработчик DOMContentLoaded запустится, когда документ загрузится, так что он увидит все элементы, включая расположенный ниже .

Но он не дожидается, пока загрузится изображение. Поэтому alert покажет нулевой размер.

На первый взгляд событие DOMContentLoaded очень простое. DOM-дерево готово – получаем событие. Хотя тут есть несколько особенностей.

DOMContentLoaded и скрипты

Когда браузер обрабатывает HTML-документ и встречает тег , он должен выполнить его перед тем, как продолжить строить DOM. Это делается на случай, если скрипт захочет изменить DOM или даже дописать в него ( document.write ), так что DOMContentLoaded должен подождать.

Поэтому DOMContentLoaded определённо случится после таких скриптов:

    

В примере выше мы сначала увидим «Библиотека загружена…», а затем «DOM готов!» (все скрипты выполнены).

Скрипты, которые не блокируют DOMContentLoaded

Есть два исключения из этого правила:

  1. Скрипты с атрибутом async , который мы рассмотрим немного позже, не блокируют DOMContentLoaded.
  2. Скрипты, сгенерированные динамически при помощи document.createElement(‘script’) и затем добавленные на страницу, также не блокируют это событие.

DOMContentLoaded и стили

Внешние таблицы стилей не затрагивают DOM, поэтому DOMContentLoaded их не ждёт.

Но здесь есть подводный камень. Если после стилей у нас есть скрипт, то этот скрипт должен дождаться, пока загрузятся стили:

   

Причина в том, что скрипту может понадобиться получить координаты или другие свойства элементов, зависящих от стилей, как в примере выше. Естественно, он должен дождаться, пока стили загрузятся.

Так как DOMContentLoaded дожидается скриптов, то теперь он так же дожидается и стилей перед ними.

Встроенное в браузер автозаполнение

Firefox, Chrome и Opera автоматически заполняют поля при наступлении DOMContentLoaded .

Например, если на странице есть форма логина и пароля и браузер запомнил значения, то при наступлении DOMContentLoaded он попытается заполнить их (если получил разрешение от пользователя).

Так что, если DOMContentLoaded откладывается из-за долгой загрузки скриптов, в свою очередь – откладывается автозаполнение. Вы наверняка замечали, что на некоторых сайтах (если вы используете автозаполнение в браузере) поля логина и пароля не заполняются мгновенно, есть некоторая задержка до полной загрузки страницы. Это и есть ожидание события DOMContentLoaded .

window.onload

Событие load на объекте window наступает, когда загрузилась вся страница, включая стили, картинки и другие ресурсы. Это событие доступно через свойство onload .

В примере ниже правильно показаны размеры картинки, потому что window.onload дожидается всех изображений:

  

window.onunload

Когда посетитель покидает страницу, на объекте window генерируется событие unload . В этот момент стоит совершать простые действия, не требующие много времени, вроде закрытия связанных всплывающих окон.

Обычно здесь отсылают статистику.

Предположим, мы собрали данные о том, как используется страница: клики, прокрутка, просмотры областей страницы и так далее.

Естественно, событие unload – это тот момент, когда пользователь нас покидает и мы хотим сохранить эти данные.

Для этого существует специальный метод navigator.sendBeacon(url, data) , описанный в спецификации https://w3c.github.io/beacon/.

Он посылает данные в фоне. Переход к другой странице не задерживается: браузер покидает страницу, но всё равно выполняет sendBeacon .

Его можно использовать вот так:

let analyticsData = < /* объект с собранными данными */ >; window.addEventListener("unload", function() < navigator.sendBeacon("/analytics", JSON.stringify(analyticsData)); >);
  • Отсылается POST-запрос.
  • Мы можем послать не только строку, но так же формы и другие форматы, как описано в главе Fetch, но обычно это строковый объект.
  • Размер данных ограничен 64 Кб.

К тому моменту, как sendBeacon завершится, браузер наверняка уже покинет страницу, так что возможности обработать ответ сервера не будет (для статистики он обычно пустой).

Для таких запросов с закрывающейся страницей есть специальный флаг keepalive в методе fetch для общих сетевых запросов. Вы можете найти больше информации в главе Fetch API.

Если мы хотим отменить переход на другую страницу, то здесь мы этого сделать не сможем. Но сможем в другом месте – в событии onbeforeunload .

window.onbeforeunload

Если посетитель собирается уйти со страницы или закрыть окно, обработчик beforeunload попросит дополнительное подтверждение.

Если мы отменим это событие, то браузер спросит посетителя, уверен ли он.

Вы можете попробовать это, запустив следующий код и затем перезагрузив страницу:

window.onbeforeunload = function() < return false; >;

По историческим причинам возврат непустой строки так же считается отменой события. Когда-то браузеры использовали её в качестве сообщения, но, как указывает современная спецификация, они не должны этого делать.

window.onbeforeunload = function() < return "Есть несохранённые изменения. Всё равно уходим?"; >;

Поведение было изменено, потому что некоторые веб-разработчики злоупотребляли этим обработчиком события, показывая вводящие в заблуждение и надоедливые сообщения. Так что, прямо сейчас старые браузеры всё ещё могут показывать строку как сообщение, но в остальных – нет возможности настроить показ сообщения пользователям.

readyState

Что произойдёт, если мы установим обработчик DOMContentLoaded после того, как документ загрузился?

Естественно, он никогда не запустится.

Есть случаи, когда мы не уверены, готов документ или нет. Мы бы хотели, чтобы наша функция исполнилась, когда DOM загрузился, будь то сейчас или позже.

Свойство document.readyState показывает нам текущее состояние загрузки.

Есть три возможных значения:

  • «loading» – документ загружается.
  • «interactive» – документ был полностью прочитан.
  • «complete» – документ был полностью прочитан и все ресурсы (такие как изображения) были тоже загружены.

Так что мы можем проверить document.readyState и, либо установить обработчик, либо, если документ готов, выполнить код сразу же.

Например, вот так:

function work() < /*. */ >if (document.readyState == 'loading') < // ещё загружается, ждём события document.addEventListener('DOMContentLoaded', work); >else < // DOM готов! work(); >

Также есть событие readystatechange , которое генерируется при изменении состояния, так что мы можем вывести все эти состояния таким образом:

// текущее состояние console.log(document.readyState); // вывести изменения состояния document.addEventListener('readystatechange', () => console.log(document.readyState));

Событие readystatechange – альтернативный вариант отслеживания состояния загрузки документа, который появился очень давно. На сегодняшний день он используется редко.

Для полноты картины давайте посмотрим на весь поток событий:

Здесь документ с , и обработчиками, которые логируют события:

   log('img onload'); 

Рабочий пример есть в песочнице.

  1. [1] начальный readyState:loading
  2. [2] readyState:interactive
  3. [2] DOMContentLoaded
  4. [3] iframe onload
  5. [4] img onload
  6. [4] readyState:complete
  7. [4] window onload

Цифры в квадратных скобках обозначают примерное время события. События, отмеченные одинаковой цифрой, произойдут примерно в одно и то же время (± несколько миллисекунд).

  • document.readyState станет interactive прямо перед DOMContentLoaded . Эти две вещи, на самом деле, обозначают одно и то же.
  • document.readyState станет complete , когда все ресурсы ( iframe и img ) загрузятся. Здесь мы видим, что это произойдёт примерно в одно время с img.onload ( img последний ресурс) и window.onload . Переключение на состояние complete означает то же самое, что и window.onload . Разница заключается в том, что window.onload всегда срабатывает после всех load других обработчиков.

Итого

События загрузки страницы:

  • DOMContentLoaded генерируется на document , когда DOM готов. Мы можем применить JavaScript к элементам на данном этапе.
    • Скрипты, вроде или блокируют DOMContentLoaded, браузер ждёт, пока они выполнятся.
    • Изображения и другие ресурсы тоже всё ещё могут продолжать загружаться.
    • loading – документ грузится.
    • interactive – документ прочитан, происходит примерно в то же время, что и DOMContentLoaded , но до него.
    • complete – документ и ресурсы загружены, происходит примерно в то же время, что и window.onload , но до него.

    Как менять контент на html странице без перезагрузки страницы?

    Добрый день, я новичок в этой теме.
    У меня есть страничка index.html генерируется Python\Flask, если страничка меняется — чтобы увидеть изменения — нужно обновить страницу в браузере, оно и понятно.

    Хочу сделать так: браузер раз в 0.5 секунды запрашивает контент — если поменялся — меняет его на странице, без перезагрузки.
    Задача учебная, данных мало, можно всю страницу целиком перезагрузить. Как это сделать?

    • Вопрос задан более трёх лет назад
    • 462 просмотра

    1 комментарий

    Простой 1 комментарий

    Как изменить URL не перезагружая страницу?

    Друзья, подскажите пожалуйста, как реализовать смену URL по клику не перезагружая страницу?

    Тут если у товара переключать цвет, там форма с инпутами как понятно по исходному коду, так вот, по клику на инпуте, перезагружается только блок с фото товара, И МЕНЯЕТСЯ URL! Без перезагрузки полной страницы.
    Как это сделано. Какие технологии используют? Вообще впервые такое вижу. Подгружают контент Ajax методом похоже с другой страницы как я понимаю. Но вот про URL так и не понял. 🙁 Подскажите пожалуйста направление.

    • Вопрос задан более трёх лет назад
    • 209 просмотров

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *