コンポーネント・ハイドレーション

ハイドレーションでは、HTMLがブラウザでレンダリングされるときに、JavaScript動作をページのコンパイル済HTMLに追加する処理を参照します。

たとえば、マスター/詳細としてレンダリングするページに2つのコンポーネントがある場合、マスターのアイテムをクリックすると、詳細コンポーネントを更新する必要があります。これは、ページで実行されるJavaScriptによってすべて処理されます。これを動作させるには、on clickイベント・ハンドラをマスター・コンポーネントの要素に追加し、リスナーを詳細コンポーネント・コンテナに追加することで、2つのコンポーネントがページにレンダリングされた後で、これらのコンポーネントのHTMLをハイドレーションして、on clickイベントがイベントを渡したペイロードに基づいて発生したときに再度レンダリングする必要があります。

コンポーネント・コンパイラがHTMLをページに挿入します。コンポーネントでイベント・ハンドラのようなものを追加するために実行時に実行される追加のJavaScriptが必要な場合、インラインのJavaScriptまたはハイドレーション関数など、オプションがいくつかあります。選択するソリューションは要件によって異なります。

インラインJavaScript

返されたコンパイル済マークアップに<script>タグを直接挿入できます。スクリプトでは、ページ実行を実行します。

例:

<script src="/_sitesclouddelivery/renderer/libs/scs-core/jssor-
slider/js/jssor.slider.min.js" type="text/javascript"></script>
<div id="slider_container_c46b122d-978a-429d-aa25-9b5698428f6f" 
style="position: relative; top: 0px; left: 0px; height: 400px; width: 600px;
background-color: rgb(68, 68, 68); visibility: visible;" data-jssor-
slider="1">
. . .
</div>
<script>
        (function () {
            // get the required options
            var options = 
{"$FillMode":2,"$AutoPlay":false,"$AutoPlayInterval":3000,"$SlideDuration":50
0,"$ArrowKeyNavigation":true,"$HWA":false,"$BulletNavigatorOptions":{"$Chance
ToShow":1,"$AutoCenter":1,"$SpacingX":5},"$ArrowNavigatorOptions":{"$ChanceTo
Show":1,"$AutoCenter":2,"$Steps":1},"$ThumbnailNavigatorOptions":{"$ChanceToS
how":0,"$DisplayPieces":7,"$SpacingX":8,"$ParkingPosition":240}};

            // select the JSSOR value options
            options.$BulletNavigatorOptions.$Class = $JssorBulletNavigator$;
            options.$ArrowNavigatorOptions.$Class = $JssorArrowNavigator$;
            options.$ThumbnailNavigatorOptions.$Class = 
$JssorThumbnailNavigator$;

            // create the slider
            var slider = new $JssorSlider$("slider_container_c46b122d-978a-
429d-aa25-9b5698428f6f", options);
  
            // resize, maintaining aspect ratio
            var container = slider.$Elmt.parentElement;
            if (container) {
                 slider.$ScaleWidth(container.getBoundingClientRect().width);
            }
        })();
    </script>

ハイドレーション関数

JavaScriptをインライン化するのではなく、ハイドレーション関数をrender.jsファイルに含め、コンパイル済マークアップを返すときに実行時にコンポーネントでハイドレーションが必要になることに注意します。このハイドレーションでは<script>タグの繰返しを回避し、既存のJavaScriptコードを活用してイベントを管理できます。

render.jsファイルをロードしても、render()関数はハイドレーション時にコールされませんhydrate()関数のみがコールされます。

注:

コンパイル済コンポーネントでハイドレーションが不要な場合、コンポーネントのrender.jsファイルはロードされません。

たとえば、カスタム・コンテンツ・レイアウト・コンパイラでは- { hydrate: true }が返されます。

return Promise.resolve({
    content: compiledContent,

    hydrate: true // note that we want to hydrate this component using the 
render.js hydrate() function. This is required for when the user clicks on 
the author
});

さらに、必要に応じて、カスタム・コンパイラではハイドレーション・プロパティを追加でき、これは実行時に検索されます。例:

Compiler: 
        // calculate the hydrate data
        content.hydrateData = JSON.stringify({
            contentId: content.id,
            authorName: content.fields['starter-blog-author_name']
        });
. . .

Template: 
<div class="author-container" data-hydrate="{{hydrateData}}">

最後に、コンポーネントでハイドレーションが必要な場合、実行時にコンポーネントのrender.jsファイルがロードされ、hydrate()関数がコールされ、コンパイル済マークアップを含むコンテナ<div>が渡されます。

たとえば、render.jsでは、hydrate()関数は次のようになります。

function selectAuthor(parentObj, contentId, authorName) {
    var $parentObj = $(parentObj);
    $parentObj.find(".author-name").click($.proxy(function () {
        $(".author-name").removeClass('author-selected');
        $(event.target).addClass('author-selected');
    }, self));
    if (window.location.href.indexOf("default=" + contentId) >= 0) {
        $(".author-name").each(function () {
            if (this.innerText === authorName) {
                $(this).addClass('author-selected');
            }
        });
    }
}
. . .
 
 
    hydrate: function (parentObj) {
        var $parentObj = $(parentObj),
            hydrateData = $parentObj.find('.author-container').attr('data-
hydrate');
        if (hydrateData) {
            var data = JSON.parse(hydrateData);
            selectAuthor(parentObj, data.contentId, data.authorName);
        }
    },
    render: function (parentObj) {
    . . .
        try {
            // Mustache
            template = Mustache.render(templateHtml, content);
 
            if (template) {
                $(parentObj).append(template);
            }
            selectAuthor(parentObj, this.contentItemData.id, 
content.fields['starter-blog-author_name']);
        } catch (e) {
            console.error(e.stack);
        }
    }