FEDev Story

Swiper.js와 Ajax 호출을 이용한 동적 슬라이드 구현 본문

Web.Dev

Swiper.js와 Ajax 호출을 이용한 동적 슬라이드 구현

지구별72 2019. 3. 26. 15:36

문제점

Swiper.js를 사용하여 슬라이드 적용시 좌우로 무한루프를 적용하기 위해 아래와 같이 옵션을 설정할 수 있다.

{loop:true]

문제는 무한 루프를 적용하기 위해 Swiper.js는 DOM을 좌우로 복사하게 된다.

즉 카테고리가 4개라면 다음과 같이 DOM을 복사한다.

카테고리 4개 * 3 = 12개의 DOM 생성

복사된 DOM 자체는 무겁지 않으나 로딩시 데이트를 한번에 불러와 복사된 DOM에 적용하는 과정에서 성능 저하를 가져오게 된다.

카테고리가 많아질 수록 성능이 더 저하될 수 밖에 없는 구조이다.

 

<section class="categoryReview">
    <div class="swiper-container swiperSlide reviewTabs">
        <ul class="swiper-wrapper tabs">
            <li class="swiper-slide"><a nohref data-url="../data/reviewData_01.html" data-loaded=false>스킨케어</a></li>
            <li class="swiper-slide"><a nohref data-url="../data/reviewData_02.html" data-loaded=false>메이크업</a></li>
            <li class="swiper-slide"><a nohref data-url="../data/reviewData_03.html" data-loaded=false>바디/헤어/향수</a></li>
            <li class="swiper-slide"><a nohref data-url="../data/reviewData_04.html" data-loaded=false>가방/지갑</a></li>
        </ul>
    </div>

    <div class="swiper-container reviewContainer"> 
        <div class="swiper-wrapper">
            <div class="swiper-slide bestReviewArea">
            </div>
            <div class="swiper-slide bestReviewArea">
            </div>
            <div class="swiper-slide bestReviewArea">
            </div>
            <div class="swiper-slide bestReviewArea">
            </div>
        </div>
    </div>
</section>


해결책

모든 데이터를 한번에 불러오지 않도록 Ajax를 적용하여 현재 활성화된 탭에 대해서만 데이터를 불러온 후 슬라이드 될 때마다 동적으로 데이터를 가져온다. 그리고 한번 불러온 데이터는 다시 호출하지 않는 방식으로 성능을 개선할 수 있다.

이때 한가지 문제점은 슬라이드시 Ajax를 호출하여 데이터를 가져오는 과정에서 어느정도의 지연현상이 발생한다.

이를 위해 $.when()을 사용하여 이전탭, 활성탭, 다음탭의 슬라이드 데이터를 미리 가져오면 지연현상없이 자연스럽게 슬라이드를 할 수 있다.

 

var swiperFn = swiperFn || {};

swiperFn.categorySwiperModule = (function(){
    var reviewContainer, reviewTabs;
    var swiperLoaded = false;

    function initSwiper(){
        reviewContainer = new Swiper('.reviewContainer', {
            spaceBetween: 10,
            loop: true,
            loopedSlides: 4,
            lazy : {
                loadOnTransitionStart : true,
                loadPrevNext : true
            },
            on: {
                init: function(){
                    console.log('swiper initialized');
                    swiperLoaded = true
                },
                slideChangeTransitionEnd: function(swiper){
                    console.log('slide change');
                    var swiper = this;
                    var currentUrl, prevUrl, nextUrl;

                    var $activeReviewSlide = $(swiper.slides[swiper.activeIndex]);
                    var $prevReviewSlide = $(swiper.slides[swiper.activeIndex-1]);
                    var $nextReviewSlide = $(swiper.slides[swiper.activeIndex+1]);

                    if(reviewTabs !== undefined){
                        currentUrl = $('a', $(reviewTabs.slides[reviewTabs.activeIndex])).data('url');
                        prevUrl = $('a', $(reviewTabs.slides[reviewTabs.activeIndex-1])).data('url');
                        nextUrl = $('a', $(reviewTabs.slides[reviewTabs.activeIndex+1])).data('url');

                        if ($('ul', $activeReviewSlide).length === 0){
                            getData(currentUrl).done(function(data){
                                console.log('call current');
                                $activeReviewSlide.append(data);
                            });
                        }

                        if ($('ul', $prevReviewSlide).length === 0){
                            getData(prevUrl).done(function(data){
                                console.log('call prev');
                                $prevReviewSlide.append(data);
                            });
                        }

                        if ($('ul', $nextReviewSlide).length === 0){
                            getData(nextUrl).done(function(data){
                                console.log('call next');
                                $nextReviewSlide.append(data);
                            });
                        }
                    }
                }
            }
        });

        reviewTabs = new Swiper('.reviewTabs', {
            spaceBetween: 10,
            centeredSlides: false,
            slidesPerView: 'auto',
            touchRatio: 0.2,
            slideToClickedSlide: true,
            initialSlide: 0,
            loop: true,
            loopedSlides: 4,
            slideActiveClass : 'active',
            on: {
                init: function(){
                    var currentUrl = $('a', this.slides[this.activeIndex]).data('url');
                    var prevUrl = $('a', this.slides[this.activeIndex-1]).data('url');
                    var nextUrl = $('a', this.slides[this.activeIndex+1]).data('url');

                    ajaxCall(currentUrl, prevUrl, nextUrl).done(function(currentData, prevData, nextData){
                        if(currentData[1] ===  'success'){
                            $('.categoryReview .reviewContainer .swiper-slide-active').append(currentData[0]);
                        }
                        if(prevData[1] ===  'success'){
                            $('.categoryReview .reviewContainer .swiper-slide-prev').append(prevData[0]);
                        }
                        if(nextData[1] ===  'success'){
                            $('.categoryReview .reviewContainer .swiper-slide-next').append(nextData[0]);
                        }
                    });
                }
            }
        });

        reviewContainer.controller.control = reviewTabs;
        reviewTabs.controller.control = reviewContainer;
    }

    function getData(url){
        return $.get(url);
    }

    function ajaxCall(_currentUrl, _prevUrl, _nextUrl){
        var def = $.Deferred();
        $.when(getData(_currentUrl), getData(_prevUrl), getData(_nextUrl))
            .done(function(data1, data2, data3){
                def.resolve(data1, data2, data3);
            })
            return def.promise();
    }

    return {
        init: function(){
            initSwiper();
        }
    }

}());

swiperFn.categorySwiperModule.init();

 

참고문서 : 
http://michaelsoriano.com/working-with-jquerys-ajax-promises-and-deferred-objects/
http://idangero.us/swiper/api/

Comments