바닥 감지는 다음 코드로 간단하다.
//스크롤 바닥 감지 window.onscroll = function(e) { //window height + window scrollY 값이 document height보다 클 경우, if((window.innerHeight + window.scrollY) >= document.body.offsetHeight) { } };
나머지는 서버에서 페이징 처리된 데이텨 값을 가져와서 파싱후 append 로 붙여주면 된다.
무한 스크롤 처리에서 중요한 부분은
1. 마지막 페이지 인지 확인
서버에서 계산된 마지막 페이지 번호가 자사스크립트에서 현재 페이지 변수 currentPageNo 보다 작을 경우
append 로 중단처리해야 한다.
2.자바스크립트 이벤트 액션값 초기화
append 로 붙여 준후에 추가적으로 자바스크립트 이벤트 액션값을 다시 호출해서 붙여 주는 데,
예 ) like.init();
이 때 반드시 초기화 해야 중복된 자바스크립트 이벤트값이 들어가서 오류가 발생하는 것을 막을 수 있다.
초기화 방법은 다음과 같이 간단하다.
off("click")
$(".like-icon").off("click"); $(".like-icon").on("click", function (e) { like.likeAction(this); });
3. 클릭후 상세페이지 보고 나서 이전페이지로 되돌아 갈때 현재 스크롤된 페이지 유지
vue 나 react 의 싱글페이지 어플리케이션 프론트 인 SPA 인경우 에는 문제 되지 않지만,
예를 들어 한페이당 10개 데이터로 10페이지까지 무한 스크롤로 표시 될 경우 맨 하단에에는 100개 표시 될 것이다.
이 때 맨하단에 데이터를 클릭후 되돌아기 버튼을 하면 최상단으로 옮겨지는 이것을 방지 하기위해 는 쿠키값이나
클라이언튼 세션 에 데이터를 저장해야 될 것이다.
다음 을 참조
https://macaronics.net/index.php/m04/jquery/view/1752
https://velog.io/@eunoia/무한-스크롤Infinite-scroll-구현하기
4. 모바일경우에는 바닥 값이 인식이 안될 경우 다음을 참조
https://macaronics.net/index.php/m04/jquery/view/1752
참조 예)
let currentPageNo=1; infinityScroll={ init:function(){ this.getList(); //스크롤 바닥 감지 window.onscroll = function(e) { //window height + window scrollY 값이 document height보다 클 경우, if((window.innerHeight + window.scrollY) >= document.body.offsetHeight) { infinityScroll.getList(currentPageNo); } }; }, getList:function(pageIndex){ if(pageIndex==null || pageIndex==undefined || pageIndex==""){ pageIndex=1; } const menuActive = $("#menuActive").val(); const param={ 'pageIndex':pageIndex, 'menuActive':menuActive } $.ajax({ url:'/portal/infiniteScroll.do', type:'post', contentType:'application/json;charset=UTF-8', data:JSON.stringify(param), dataType:"json", success:function(res){ //res=JSON.parse(res); //console.log(res); //**** 서버에서 계산된 마지막 페이지 번호가 자사스크립트 currentPageNo 작을 경우 중단처리 if(currentPageNo >res.paginationInfo.lastPageNo)return; console.log(" currentPageNo {} - {}",res.paginationInfo.lastPageNo , currentPageNo , res.paginationInfo.currentPageNo); currentPageNo++; let html=""; res.resultList.forEach(function(result){ let likeActive=""; if(result.likeCnt!="0"){ likeActive='like-active'; } html +=` <div class="col-lg-4 col-sm-6 mb-4"> <div class="portfolio-item"> <a class="portfolio-link" data-bs-toggle="modal" href="#portfolioModal1" data-nttId="${result.nttId}"> <div class="portfolio-hover"> <div class="portfolio-hover-content"><i class="fas fa-plus fa-3x"></i></div> </div> <img class="img-fluid" src='/cmm/fms/getImage.do?atchFileId=${result.atchFileId}&fileSn=0"/>' alt="${result.frstRegisterNm}" /> </a> <div class="portfolio-caption"> <div class="portfolio-caption-heading"> <c:out value="${result.nttSj}" /> </div> <div class="portfolio-caption-subheading text-muted"> <div class="row"> <div class="col-md-12"> <span class="me-2 news-date" data-bs-toggle="tooltip" data-bs-placement="top" title="등록일" > <i class="fa fa-calendar" ></i> <span>${result.frstRegisterPnttm}</span> </span> <span class="me-2 news-like like-icon ${likeActive}" data-nttId="${result.nttId}" data-bs-toggle="tooltip" data-bs-placement="top" title="좋아요" > <i class="fa fa-heart heart" ></i> <span> ${result.likeTotCnt} </span> </span> <span class="me-2 news-views" data-bs-toggle="tooltip" data-bs-placement="top" title="조회수" > <i class="fa fa-eye"></i> <span>${result.inqireCo}</span> </span> <span class="me-2 news-comments" data-bs-toggle="tooltip" data-bs-placement="top" title="댓글수" > <i class="fa fa-comments" id="fa-comments"></i> <span>${result.commentTotCnt}</span> </span> </div> </div> </div> </div> </div> </div> `; });//forEach if(res.resultCnt==0){//전체 게시물 갯수가 0이면 html=` <div class="col-lg-12 col-sm-12 mb-12 text-center" > <h5>등록된 데이터가 없습니다.</h5> </div> `; } $("#contentList").append(html); //이벤트 처리값을 호출해서 붙여 준다 // 이때 .off("click"); 이벤트 초기화 like.init(); modalAction.init(); var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')) var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { return new bootstrap.Tooltip(tooltipTriggerEl) }) }, error:function(res){ console.log("error"); console.log(res); } }); } } infinityScroll.init();
let like={ init:function(){ $(".like-icon").off("click"); $(".like-icon").on("click", function (e) { like.likeAction(this); }); }, likeAction:function(e){ console.log("likeAction ->"); console.log(e); const nttId =$(e).attr("data-nttId"); console.log(nttId); const param={ 'nttId':nttId } $.ajax({ url:'/portal/like/likeAction.do', type:'post', contentType:'application/json;charset=UTF-8', data:JSON.stringify(param), success:function(res){ //console.log(res); $(e).removeClass("like-active"); let cnt=$(e).children("span").text(); //console.log("0좋아요갯수:"+ cnt); cnt=cnt.replace(/\n/g, ""); cnt=cnt.replace(/\s*/g, ""); cnt=Number(cnt); cnt=parseInt(cnt); if(res=="1"){ $(e).addClass("like-active"); cnt++; tInfo("좋아요!",""); }else{ tWarning("좋아요 취소!"); cnt--; $(e).removeClass("like-active"); } $(e).children("span").text(cnt); }, error:function(res){ /* console.log("error"); console.log(res);*/ } }); } } like.init();
댓글 ( 4)
댓글 남기기