Битрикс. Композитный сайт. Часть 3 из 3

27.11.2018

Теги: CMSWeb-разработкаБитриксКешированиеКомпозитныйСайтНастройкаОтложенныеФункции

Класс FrameStatic

Класс FrameStatic просто расставляет метки начала и конца динамической зоны. И потом, когда страница сформирована, по этим меткам вырезается контент динамической области.

<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");
$APPLICATION->SetTitle("Случайные элементы");
?>
<h1>Случайные элементы</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<?php
$randomElementsFrame = new \Bitrix\Main\Page\FrameStatic('random-elements-label');
// устанавливаем заглушку, которая будет показана на первом хите композита
$randomElementsFrame->setStub('Загрузка...');
// начинаем буферизацию
$randomElementsFrame->startDynamicArea();
// подключаем компонент, который формирует блок случайных элементов
$APPLICATION->IncludeComponent(
    "tokmakov:iblock.random",
    "",
    array(/*...*/)
);
// завершаем буферизацию
$randomElementsFrame->finishDynamicArea();
?>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");
?>
<h1>Случайные элементы</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<div id="bxdynamic_random-elements-label_start" style="display:none"></div>
Загрузка...
<div id="bxdynamic_random-elements-label_end" style="display:none"></div>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>

<h1>Случайные элементы</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<div id="bxdynamic_random-elements-label_start" style="display:none"></div>
<section id="iblock-random-items">
    <article>
        <a href="/articles/element/code/dalmatin/">
            <img src="/upload/iblock/c96/c9661e9c9cae4c7bca190da9289b8fbc.jpg"
                 alt="Далматин. Породы собак" title="Далматин. Породы собак"
                 title="Далматин. Породы собак" title="Далматин. Породы собак" />
        </a>
        <h4><a href="/articles/element/code/dalmatin/">Далматин</a></h4>
        <p>Просмотров: 0</p>
    </article>
    <article>..........</article>
    <article>..........</article>
    <article>..........</article>
</section>
<div id="bxdynamic_random-elements-label_end" style="display:none"></div>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>

Все бы ничего, но после ajax-запроса, когда на страницу вместо заглушки вставляется динамический контент, элементы страницы «прыгают», что выглядит не очень красиво. Давайте это исправим — добавим свой контейнер для динамического контента, зададим для него min-height и ajax-loader.gif в качестве background-image. И используем вызов метода setAnimation(), который плавно изменяет opacity контейнера от нуля до единицы после вставки динамического контента:

<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");
$APPLICATION->SetTitle("Случайные элементы");
?>
<h1>Случайные элементы</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<div id="random-elements">
<?php
$randomElementsFrame = new \Bitrix\Main\Page\FrameStatic('random-elements-label');
// задаем контейнер, внутри которого будет сначала пусто, а потом динамический контент
$randomElementsFrame->setContainerID('random-elements');
// добавляем анимацию динамического контента после ajax-запроса; opacity плавно изменяется от 0 до 1
$randomElementsFrame->setAnimation(true);
// начинаем буферизацию 
$randomElementsFrame->startDynamicArea();
// вызываем наш компонент, который формирует блок случайных элементов
$APPLICATION->IncludeComponent(
    "tokmakov:iblock.random",
    "",
    array(/*...*/)
);
// завершаем буферизацию
$randomElementsFrame->finishDynamicArea();
?>
</div>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");
?>
#random-elements {
    min-height: 242px;
    background: url(../img/ajax-loader.gif) #fff no-repeat center center;
}
<h1>Случайные элементы</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<div id="random-elements"></div>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
</div>

<h1>Случайные элементы</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<div id="random-elements">
<section id="iblock-random-items">
    <article>
        <a href="/articles/element/code/abissinskaya-koshka/">
            <img src="/upload/iblock/2cb/2cba6cc8ba68c914852b9c5b2f95b387.jpg"
                 alt="Абиссинская кошка. Породы кошек. Статьи о домашних животных"
                 title="Абиссинская кошка. Породы кошек. Статьи о домашних животных" />
        </a>
        <h4><a href="/articles/element/code/abissinskaya-koshka/">Абиссинская кошка</a></h4>
        <p>Просмотров: 8</p>
    </article>
    <article>..........</article>
    <article>..........</article>
    <article>..........</article>
</section>
</div>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>

Класс FrameBuffered

Этот класс мы уже использовали, когда адаптировали шаблон компонента для работы в композитном режиме. Именно объект этого класса создаётся при вызове метода $this->createFrame() в шаблоне.

$frame = new \Bitrix\Main\Page\FrameBuffered('some-dinamic-area'); // или вызов метода $this->createFrame() в шаблоне
$frame->begin();
    // динамический контент
$frame->beginStub();
    // html-код заглушки
$frame->end();

Код между вызовами begin()…beginStub() и beginStub()…end() выполняется всегда. И на первом хите к странице (на котором создается кеш) и на ajax-хите. Эти методы занимаются буферизацией контента и не являются аналогами конструкции if…else. Вызов $frame->end() завершает разметку динамичной части.

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

Давайте рассмотрим использование этого класса на примере компонента, который выводит на страницу случайные элементы инфоблока:

<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");
$APPLICATION->SetTitle("Случайные элементы");
?>
<h1>Случайные элементы</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<?php
$frame = new \Bitrix\Main\Page\FrameBuffered('random-elements-label');
$frame->begin();
    // вызываем наш компонент, который формирует блок случайных элементов
    $APPLICATION->IncludeComponent(
        "tokmakov:iblock.random",
        "",
        array(/*...*/)
    );
$frame->beginStub();
?>
    <section id="random-elements-stub">
        <article></article>
        <article></article>
        <article></article>
        <article></article>
    </section>
<?php
$frame->end();
?>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");
?>

Для заглушки зададим стили:

#random-elements-stub {
    overflow: hidden;
    margin: 15px 0;
    background: #f5f5f5;
    border: 1px solid #d1d1d1;
    border-radius: 10px;
    padding: 10px;
}
    #random-elements-stub > article {
        float: left;
        width: 24%;
        box-sizing: border-box;
        border: 1px solid #d1d1d1;
        padding: 10px;
        border-radius: 10px;
        background: #fff;
        margin-right: 1.33333%;
        min-height: 220px;
        background: url(../img/ajax-loader.gif) #fff no-repeat center center;
    }
    #random-elements-stub > article:last-child {
        margin-right: 0;
    }

Страница, полученная из кеша (с заглушкой):

<h1>Случайные элементы</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<div id="bxdynamic_random-elements-label_start" style="display:none"></div>
<section id="random-elements-stub">
    <article></article>
    <article></article>
    <article></article>
    <article></article>
</section>
<div id="bxdynamic_random-elements-label_end" style="display:none"></div>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>

Страница после выполнения ajax-запроса:

<h1>Случайные элементы</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<div id="bxdynamic_random-elements-label_start" style="display:none"></div>
<section id="iblock-random-items">
    <article>
        <a href="/articles/element/code/labrador/">
            <img src="/upload/iblock/89e/89ec16065d8ddd149ac22001916f9f67.jpg"
                 alt="Лабрадор. Служебные породы. Статьи о домашних животных"
                 title="Лабрадор. Служебные породы. Статьи о домашних животных" />
        </a>
        <h4><a href="/articles/element/code/labrador/">Лабрадор</a></h4>
        <p>Просмотров: 0</p>
    </article>
    <article>..........</article>
    <article>..........</article>
    <article>..........</article>
</section>
<div id="bxdynamic_random-elements-label_end" style="display:none"></div>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>

Вместо заключения

Как уже было отмечено ранее, по умолчанию компонент голосует за композит, а шаблон компонента — против. Мы можем изменить это поведение по-умолчанию, с помощью вызова метода setFrameMode() в коде компонента и в коде шаблона. Например, для компонента «Случайные элементы инфоблока»

<?php
/*
 * Файл local/components/tokmakov/iblock.random/component.php
 */
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED!==true) die();

// компонент голосует против композита, его нельзя кешировать,
// иначе мы не получим случайные элементы инфоблока
$this->setFrameMode(false);
<?php
/*
 * Файл local/components/tokmakov/iblock.random/templates/.default/template.php
 */
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED!==true) die();

// шаблон компонента голосует против композита, его нельзя кешировать,
// иначе мы не получим случайные элементы инфоблока
$this->setFrameMode(false);

Теперь, если на какой-нибудь странице сайта мы подключим этот компонент, такая страница не попадет в кеш:

<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");
$APPLICATION->SetTitle("Случайные элементы");
?>
<h1>Случайные элементы</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<?php
// вызываем наш компонент, который формирует блок случайных элементов
$APPLICATION->IncludeComponent(
    "tokmakov:iblock.random",
    "",
    array(/*...*/)
);
?>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");
?>

Чтобы страница с таким компонентом все-таки попала в кеш, можно запретить компоненту и шаблону голосовать «против» — считаем, что шаблон и компонент проголосовали «за»:

<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");
$APPLICATION->SetTitle("Случайные элементы");
?>
<h1>Случайные элементы</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<?php
$staticHTMLCache = \Bitrix\Main\Data\StaticHTMLCache::getInstance();
// запрещаем компоненту случайных элементов голосовать против композита
$staticHTMLCache->disableVoting();
// вызываем наш компонент, который формирует блок случайных элементов
$APPLICATION->IncludeComponent(
    /*...*/
);
// компоненты ниже будут голосовать за или против композита как обычно
$staticHTMLCache->enableVoting();
?>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");
?>

Теперь страница попадет в кеш, но будет постоянно перезаписываться на ajax-хите. Давайте вообще отменим ajax-запрос для этой страницы:

<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");
$APPLICATION->SetTitle("Случайные элементы");
/*
 * Создаем кеш сроком хранения 60 секунд
 */
$composite = \Bitrix\Main\Page\Frame::getInstance();
$composite->setAutoUpdate(false);
$composite->setAutoUpdateTTL(60);
/*
 * Запрещаем всем компонентам ниже голосовать
 */
$staticHTMLCache = \Bitrix\Main\Data\StaticHTMLCache::getInstance();
$staticHTMLCache->disableVoting();
?>
<h1>Случайные элементы</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<?php
// вызываем наш компонент, который формирует блок случайных элементов
$APPLICATION->IncludeComponent(
    /*...*/
);
?>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore...
</p>
<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");
?>

Теперь страница просто кешируется и не выполняет ajax-запрос до тех пор, пока не истечет её время жизни — 60 секунд. Этот фоновый запрос перезапишет кеш — и у нас будет новый набор случайных элементов на следующие 60 секунд.

Поиск: CMS • Web-разработка • Битрикс • Кеширование • Композитный сайт • FrameStatic • setStub • startDynamicArea • finishDynamicArea • setContainerID • setAnimation • FrameBuffered • begin • beginStub • end • Отложенные функции • Frame • StaticHTMLCache

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.