24  /  26

Как быть с "морганием" информации в динамической зоне

Просмотров: 26632
Дата последнего изменения: 19.08.2021
Роберт Басыров
Сложность урока:
2 уровень - несложные понятия и действия, но не расслабляйтесь.
1
2
3
4
5
Недоступно в лицензиях:
Ограничений нет

Пример "моргания": счетчик товаров в корзине пользователя находится в динамической области. Некрасиво прыгает цифра: сначала ноль, потом один. Почему это происходит?

  1. В файл кеша записывается заглушка "0 товаров в корзине".
  2. Страница из кеша отдается пользователю и показывается.
  3. Даже если второй, аяксовый, хит с нужными данными приходит раньше, чем отрендерилась страница, все равно пользователь на мгновение видит заглушку.
  4. Это происходит из-за того, что все вставки в innerHTML (в том числе из sqlite) происходят на событии DOMContentLoaded.
  5. Хотя в большинстве случаев виноват даже не DOMContentLoaded, а долгое выполнение аяксового запроса.

Чтобы побороть "моргание", нужно вставить актуальные данные в страницу до того, как она покажется пользователю. Как вставить до рендеринга? есть два варианта:

  1. document.write - это конструкция останавливает рендеринг страницы, для того, чтобы на лету вставить в DOM новый HTML. Разработчики браузеров не рекомендуют ее использовать, но она работает.
  2. Разместить Javascript в странице так, чтобы он располагался после HTML'я, к которому обращается. Это старый забытый способ начала 2000-x годов, когда еще jQuery'ая $.ready() не замылила всем глаза. $.ready() или битриксовая BX.ready - это выполнение кода на событии DOMContentLoaded. Это событие гарантирует, что DOM построен и к нему можно безопасно обращаться. Минус этого события в том, что на больших страницах интерфейс уже успевает пользователю показаться, отсюда и моргание.
<!doctype html>
<html>
<body>
<div id="box" style="width: 100px; height: 100px; background: red;"></div>
<script>document.getElementById("box").style.background = "blue";</script>
<table><tr><td>some html below</td></tr></table>
</body>
</html>>

Есть вероятность нарваться на Exception, поэтому можно подстраховаться:

function changeBox()
{
   document.getElementById("box").style.background = "blue";
}

var box = document.getElementById("box");
if (box)
{
   changeBox();
}
else
{
   BX.ready(function() { changeBox(); });
}

Актуальные данные можно получить из:

  1. Cookies
  2. SQLite
  3. LocalStorage

Самый приемлемый вариант - это localStorage. Это key-value хранилище, которое поддерживается всеми браузерами, даже IE8. Данные localStorage доступны мгновенно сразу во всех вкладках. То есть, если у пользователя открыто 10 вкладок магазина и он в одной из них жмет "Добавить в корзину", то через событие localStorage'а можно мгновенно поменять во всех вкладках счетчик корзины.

Для localStorage в Bitrix Framework есть своя обвязка под названием BX.localStorage. Она позволяет указывать время хранения данных. Основные методы:

События:

  • BX.addCustomEvent("onLocalStorageSet", function(data) { console.log(data.key, data.value) });
  • BX.addCustomEvent("onLocalStorageRemove", function(data) {});
  • BX.addCustomEvent("onLocalStorageChange", function(data) {});

В итоге: счетчик корзины и имя пользователя можно кешировать в localStorage и использовать эти данные для борьбы с "морганием".


Что ещё нужно учитывать чтобы избежать "моргания":

  • Старайтесь делать верстку так, чтобы вставка динамических областей не приводила к прыганию соседних элементов.
  • C помощью метода setAnimation(true) можно добавить эффект плавного появления контента.
  • Экспериментируйте с содержимым заглушек. Заглушка может быть пустой, а может повторять содержимое динамической области.

12
Курсы разработаны в компании «1С-Битрикс»

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