구성요소 하이드레이션

하이드레이션은, 브라우저에서 HTML을 렌더링할 때 페이지의 컴파일된 HTML에 JavaScript 동작을 다시 추가하는 프로세스를 말합니다.

예를 들어, 페이지에 마스터/디테일로 렌더링할 두 구성요소가 있는 경우 마스터의 항목을 누르면 디테일 구성요소를 업데이트해야 합니다. 이것은 모두 페이지에서 실행되는 JavaScript에 의해 처리됩니다. 이 동작이 작동하려면 두 구성요소가 페이지에 렌더링된 후 HTML을 하이드레이션해야 합니다. on click 이벤트 처리기를 마스터 구성요소의 요소와 디테일 구성요소 컨테이너의 리스너에 추가하여 이벤트에 전달된 페이로드에 따라 on click 이벤트가 발생할 때 다시 렌더링되도록 합니다.

구성요소 컴파일러는 페이지에 HTML을 삽입합니다. 구성요소가 런타임에 이벤트 처리기 따위를 추가하는 별도의 JavaScript를 실행해야 하는 경우 인라인 JavaScript 또는 Hydrate 함수의 두 가지 옵션이 있습니다. 어떤 솔루션을 선택할지는 요구사항에 따라 다릅니다.

인라인 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>

Hydrate 함수

JavaScript 인라인 대신, render.js 파일에 hydrate 함수를 포함할 수 있습니다. 이때 컴파일된 마크업을 반환할 때 런타임에 구성요소 하이드레이션이 필요합니다. 이 하이드레이션은 반복되는 <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
});

또한 필요한 경우 사용자정의 컴파일러는 런타임에 발견될 hydrate 속성을 추가할 수 있습니다. 예를 들어, 다음과 같습니다.

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);
        }
    }