Задать вопрос
JastaFly
@JastaFly

Композитный сайт и $frame->beginStub()?

Доброго всем времени суток! Есть сайт на Битриксе со включенной технологий композитный сайт. На сайте не работала кнопка авторизации, при клике на которую вызывается модалка с формой для логина и пароля, просто в какой-то момент с неё начал слетать eventListener. По ходу копания в проблеме выяснил проблема в композите и если его отрубить то всё прекрасно работает. Код кнопки выглядит следующим образом:
<?
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true)
    die();

use Bitrix\Main\Localization\Loc;
use Citfact\SiteCore\EventAlert\EventAlertManager;

$frame = new \Bitrix\Main\Page\FrameBuffered('authorize_'.ToLower($arParams['ID']));
$frame->begin();
$cUser = new \CUser();
if ($cUser->IsAuthorized()) {

    $userId = (int)$cUser->GetID();

    // Счетчик оповещений о событиях
    $alertManager = new EventAlertManager($userId);
    $allAlertsCnt = $alertManager->getAllAlertsCnt();
    ?>
    <div class="header__link header__link--auth header__lk"
        <?= ((int)$allAlertsCnt > 0 ) ? 'not_empty' : 'empty'; ?>
         data-alerts-num-wrap>
        <svg class='i-icon header-nav__link'>
            <use xlink:href='#icon-personal'></use>
        </svg>
        <span data-alerts-num><?= $allAlertsCnt; ?></span>
        <div class="header-nav__down">
            <ul class="header-nav__down-list">
                <li>
                    <a href="<?= SITE_DIR; ?>account">
                        <?= Loc::getMessage('HEADER_PERSONAL_AREA'); ?>
                    </a>
                </li>
                <li>
                    <a href="<?= SITE_DIR; ?>?logout=yes">
                        <?= Loc::getMessage('HEADER_EXIT'); ?>
                    </a>
                </li>
            </ul>
        </div>
    </div>
<? } else { ?>
    <div class="header__link header__link--right">
        <a data-href="/local/include/modals/auth.php?site=<?= SITE_ID; ?>" class="header__link header__link--auth" data-modal="ajax">
            <svg class='i-icon'>
                <use xlink:href='#icon-personal'></use>
            </svg>
        </a>
        <a data-href="/local/include/modals/auth.php?site=<?= SITE_ID; ?>" class="header__link header__link--auth header__link__button" data-modal="ajax"><?= Loc::getMessage('CITFACT_TEMPLATE_SUBSCRIBE_BUTTON'); ?></a>
    </div>
<? } ?>
<? $frame->beginStub(); ?>
    <a data-href="/local/include/modals/auth.php?site=<?= SITE_ID; ?>" class="header__link header__link--auth" data-modal="ajax">
        <svg class='i-icon'>
            <use xlink:href='#icon-personal'></use>
        </svg>
    </a>
<? $frame->end(); ?>

Так вот если удалить $frame->beginStub() то кнопка начинает работать. Плиз подскажите в чем причина?!?? Просто не до конца понял как работает композит?!??
Заранее всем спасибо)
  • Вопрос задан
  • 692 просмотра
Подписаться 1 Простой Комментировать
Решения вопроса 1
winer
@winer
занимаюсь разработкой сайтов на 1c-bitrix
Чтобы разобраться в проблеме надо понимать как работает композит.
Вот так размечается динамический контент и его заглушка внутри шаблона компонента:
$frame = new \Bitrix\Main\Page\FrameBuffered("my_dynamic"); 
$frame->begin();
  // Содержание динамической области
$frame->beginStub();
  // Заглушка
$frame->end();

При первоначальной загрузке страницы, браузер получает HTML в котором отсутствует динамический контент. На его месте находятся заглушки.
После загрузки страницы у Вас выполняется JS скрипт, который навешивает обработчик на вашу кнопку. Но кнопка у вас из заглушки.
После уже сам Битрикс загружает на место заглушки динамический контент. В DOM модели это будет уже другая кнопка и на ней не будет вашего обработчика.

Поэтому Вам надо либо инициализировать обработчик из динамической области, либо изначально вешать событие не на саму кнопку. Например в jQuery это можно сделать так
$(document).on('click', '.header__link.header__link--auth', callback);
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Вангую что проблема вовсе не в композите, а в js слушателях которые традиционно навешиваются по событию готовности страницы.
В итоге у вас сначала грузится статическая часть кэшированная композитом, потом срабатывают скрипты. Потом подргужается блок с кнопкой. Но так как скрипты уже отработали когда кнопки не было, то и никакой слушатель за нее не зацепился. А когда кнопка появилась в странице, поезд со слушателями уже давно ушел.

js не должен полагаться на готовность DOM который не создается им самим, как за многие годы многих приучил делать jQuery.
Если события назначаются элементам DOM это должен делать тот кто создают html. Если, в данном случае, html создается на сервере с помощью PHP, то и события пусть назначаются на сервере прямо в этом html.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы