IT/development

[Vue.js] 페이지네이션 처리

알 수 없는 사용자 2023. 8. 9. 05:40
반응형

부모 컴포넌트

<div id="main">
<!-- 코드 생략... -->

<!--페이지네이션 컴포넌트-->
<!-- 
props로 자식 컴포넌트로 페이지네이션 관련 parameter 5개 전달하고
자식 컴포넌트에서 @update:current-page로 데이터(page) 전달 받음
-->
<paging-component :current-page="currentPage" :first-page="firstPage" :last-page="lastPage" :start-idx="startIdx" :end-idx="endIdx" @update:current-page="onUpdateCurrentPage"></paging-component>
</div>

<script layout:fragment="script" th:inline="javascript" type="text/javascript">
        new Vue({
           //element id
           el: '#main',
           //vue에서 관리할 데이터
           data: {
                 items: [],   // 데이터 목록
                 currentPage: 1,  //현재 페이지
                 firstPage: 0,        //첫번 째 페이지
                 lastPage: 0,         //마지막 페이지
                 startIdx: 0,      //첫번 째 페이지 번호
                 endIdx: 0,       //마지막 페이지 번호
                 empNm: '',         //사원명
           },   
          //data를 기반으로 변경할 속성(data의 변경 감지)
           computed: {
            //변경된 데이터
            displayedItems() {
              return this.items;
            },
           },
           //vue 컴포넌트 화면에 렌더링 된 직후 실행(컴포넌트의 템플릿이 DOM에 추가/화면에 표시된 직후)
           mounted() {
            //데이터 조회
            this.fetchData();
           },
           methods: {
           //데이터 조회
           fetchData() {
             const url = '/api/board';
             //2번 째 parameter(queryString)
             const params = { params:
                    { currentPage: this.currentPage,
                      empNm: this.empNm
                    }
                   };
             //ajax 호출
             axios.get(url, params)
             .then(function(response) {
               this.items = response.data.list;
               this.firstPage = response.data.paging.firstPage;
               this.lastPage = response.data.paging.lastPage;
               this.startIdx = response.data.paging.firstPageNo;
               this.endIdx = response.data.paging.lastPageNo;
             }.bind(this))
             .catch(function(error) {
               // 에러 처리
               console.log(error);
             });
           },
           // 페이지 이동 이벤트 시 수행(자식 컴포넌트에서 전달받은 page)
           onUpdateCurrentPage(page) {
             this.currentPage = page;
             this.fetchData(); // fetchData() 메서드 실행
           },
           //검색
           search() {
             this.currentPage = 1;
             this.fetchData();
           },
          },
        });

자식컴포넌트

// 페이징 관련 컴포넌트
// 부모 컴포넌트에게 props로 데이터 전달 받아서 페이징 시작~종료인덱스 세팅 후 페이지네이션 처리
Vue.component('paging-component', {
    props: ['currentPage', 'firstPage','lastPage', 'startIdx', 'endIdx'],
    computed: {
    //페이징 개수 세팅(시작인덱스, 종료인덱스를 받아서 동적으로 array 세팅)
        pagedArray() {
            const pagedArr = [];
                for (let i = this.startIdx; i <= this.endIdx; i++) {
                    pagedArr.push(i);
                }
            return pagedArr;
        },
    },
    methods: {
       movePage(page) {
       	 //이벤트 발생(부모 컴포넌트에게 데이터 전달) 
         this.$emit('update:current-page', page);
       },
     },
    //페이지네이션 템플릿
    template: `        
        <div class="paging tbl-paging">
          <ul class='pagination'>
            <!--first-->
            <li class='paginate_button page-item first'>
              <button
                type='button'
                class='page-link'
                :style="{ cursor: currentPage !== firstPage ? 'pointer' : 'default' }"
                :disabled="currentPage === firstPage"
                @click="movePage(firstPage)"    
              > 
                <span class='hidden'>첫 페이지</span>
              </button>
            </li>
            <!--prev-->
            <li class='paginate_button page-item prev'>
              <button
                type='button'
                class='page-link'
                :style="{ cursor: currentPage !== firstPage ? 'pointer' : 'default' }"
                :disabled="currentPage === firstPage"
                @click="movePage(currentPage - 1)"
              >         
                <span class='hidden'>이전 페이지</span>
              </button>
            </li>   
            <!--① ~ ⑩-->    
            <li         
              class='paginate_button page-item'
              v-for="(page, index) in pagedArray"
              :key="index"  
              :class="{ 'active': currentPage === page }"
              @click="movePage(page)"       
            >                            
              <button type='button' class='page-link' style='cursor: pointer;'>
                {{ page }}
              </button>  
            </li>
            <!--next-->
            <li class='paginate_button page-item next'>
              <button
                type='button'
                :disabled="currentPage === lastPage"
                class='page-link'
                :style="{ cursor: currentPage !== lastPage ? 'pointer' : 'default' }"
                @click="movePage(currentPage + 1)"
              >     
                <span class='hidden'>다음 페이지</span>
              </button>
            </li>
            <!--last-->
            <li class='paginate_button page-item last'>
              <button
                type='button'
                :disabled="currentPage === lastPage"    
                class='page-link'
                :style="{ cursor: currentPage !== lastPage ? 'pointer' : 'default' }"
                @click="movePage(last)"
              >     
                <span class='hidden'>마지막 페이지</span>
              </button>
            </li>
          </ul>
        </div>
      `,
});
반응형