반응형
Vue와 Spring을 이용하여 Paging을 다음과 같은 페이징을 구현하는 방법을 알아보겠습니다.
Vue 프로젝트의 파일 구조와 router.js 의 코드입니다.
import Vue from "vue";
import VueRouter from "vue-router";
import Home from "@/views/Home.vue";
import Page from "@/views/Page.vue";
import List from "@/components/List.vue";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "Home",
component: Home
},
{
path: "/page",
name: "Page",
component: Page,
children:[
{
path: '/list',
component: List,
}
]
}
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
export default router;
Page.vue - 페이지 상단의 Page 를 클릭 했을 때의 코드 입니다.
<template>
<div class="about">
<h1>Pagination ( Page-Link )</h1>
<router-view/>
<page-link/>
</div>
</template>
<script>
// @ is an alias to /src
import PageLink from "@/components/PageLink.vue";
export default {
name: "Page",
components: {
PageLink
}
};
</script>
PageLink.vue - Pagination 바를 만들어주고 번호 목록을 클릭했을 때 동작하는 코드
<template>
<ul class="pagination justify-content-center">
<li class="page-item" v-if="prev">
<router-link :to="`/list?no=${ (startPageIndex - 1) * listRowCount }`" class="page-link" aria-label="Previous" @click.native="movePage(startPageIndex - 1)">
<span aria-hidden="true">«</span>
</router-link>
</li>
<li v-for="index in endPageIndex-startPageIndex + 1 " :key="index" class="page-item" :class="{active:( (startPageIndex + index - 1) == currentPageIndex)}">
<router-link :to="`/list?no=${ (startPageIndex + index - 1) * listRowCount }`" class="page-link" @click.native="movePage(startPageIndex + index - 1)">{{ startPageIndex + index - 1 }}</router-link>
<!-- <a class="page-link" href="javascript:movePage(' + i + ')">' + i + '</a> -->
</li>
<li class="page-item" v-if="next">
<router-link :to="`/list?no=${ (endPageIndex + 1) * listRowCount }`" class="page-link" aria-label="Next" @click.native="movePage(endPageIndex + 1)">
<span aria-hidden="true">»</span>
</router-link>
</li>
</ul>
</template>
<script>
import http from "@/util/http-common";
export default {
name: "row",
data() {
return {
totalListItemCount: 0,
listRowCount: 10,
pageLinkCount: 10,
currentPageIndex: 1,
pageCount: 0,
startPageIndex: 0,
endPageIndex: 0,
prev: false,
next: false
};
},
methods: {
movePage( param ) {
this.currentPageIndex = param;
this.initComponent();
},
initComponent(){
http
.get("/board/pagelink/count")
.then(({ data }) => {
this.totalListItemCount = data;
this.initUI();
})
.catch(() => {
alert("에러가 발생했습니다.");
});
},
initUI(){
this.pageCount = Math.ceil(this.totalListItemCount/this.listRowCount);
if( (this.currentPageIndex % this.pageLinkCount) == 0 ){
this.startPageIndex = ((this.currentPageIndex / this.pageLinkCount)-1)*this.pageLinkCount + 1
}else{
this.startPageIndex = Math.floor(this.currentPageIndex / this.pageLinkCount)*this.pageLinkCount + 1
}
if( (this.currentPageIndex % this.pageLinkCount) == 0 ){ //10, 20...맨마지막
this.endPageIndex = ((this.currentPageIndex / this.pageLinkCount)-1)*this.pageLinkCount + this.pageLinkCount
}else{
this.endPageIndex = Math.floor(this.currentPageIndex / this.pageLinkCount)*this.pageLinkCount + this.pageLinkCount;
}
if(this.endPageIndex > this.pageCount){
this.endPageIndex = this.pageCount
}
if( this.currentPageIndex <= this.pageLinkCount ){
this.prev = false;
}else{
this.prev = true;
}
if(this.endPageIndex >= this.pageCount){
this.endPageIndex = this.pageCount;
this.next = false;
}else{
this.next = true;
}
}
},
watch:{
currentPageIndex: function(){
this.initUI();
}
},
created() {
this.initComponent();
},
mounted(){
this.$router.push('list?no=' + this.listRowCount)
}
};
</script>
List.vue - 목록을 출력해주기 위한 틀이 되는 컴포넌트. axios로 backend와 통신하여 데이터를 가져옵니다.
<template>
<div>
<div v-if="items.length">
<table class="table table-bordered table-condensed">
<colgroup>
<col :style="{ width: '5%' }" />
<col :style="{ width: '50%' }" />
<col :style="{ width: '10%' }" />
<col :style="{ width: '25%' }" />
</colgroup>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>날짜</th>
</tr>
<list-row
v-for="(item, index) in items"
:key="`${index}_items`"
:no="item.no"
:title="item.title"
:writer="item.writer"
:regtime="item.regtime"
/>
</table>
</div>
<div v-else>글이 없습니다.</div>
</div>
</template>
<script>
import http from '@/util/http-common';
import ListRow from '@/components/Row.vue';
export default {
name: 'list',
components: {
ListRow,
},
data: function() {
return {
items: [],
pageLimit : 10,
pageOffet : 0
};
},
created() {
this.initComponent();
},
watch: {
'$route.query': function(){
this.initComponent();
}
},
methods: {
initComponent(){
http
.get('/board/pagelink',{
params: { limit: this.pageLimit, offset: `${this.$route.query.no - this.pageLimit}`}
})
.then(({ data }) => {
this.items = data
})
.catch(() => {
alert('에러가 발생했습니다.');
});
}
}
};
</script>
<style></style>
Row.vue - 가져온 하나하나의 데이터를 출력하기 위한 컴포넌트
<template>
<tr>
<td>{{ no }}</td>
<td>
<router-link :to="`/read?no=${no}`">{{ title }}</router-link>
</td>
<td>{{ writer }}</td>
<td>{{ getFormatDate(regtime) }}</td>
</tr>
</template>
<script>
import moment from 'moment';
export default {
name: 'row',
props: {
no: { type: Number },
writer: { type: String },
title: { type: String },
regtime: { type: String },
},
methods: {
getFormatDate(regtime) {
return moment(new Date(regtime)).format('YYYY.MM.DD');
},
},
};
</script>
이제부터 Vue와 axios 로 통신하는 Backend Spring 코드를 알아 보겠습니다. 참고로 Mybatis 퍼시스턴트 프레임워크를 사용하였습니다.
Controller.java
@ApiOperation(value = "limit offset 에 해당하는 게시글의 정보를 반환한다. ", response = List.class)
@GetMapping(value = "/pagelink")
public ResponseEntity<List<Board>> selectBoardLimitOffset(int limit, int offset) throws Exception {
logger.debug("selectBoardLimitOffset - 호출");
System.out.println("limit : " + limit + " / offset : " + offset);
return new ResponseEntity<List<Board>>(boardService.selectBoardLimitOffset(limit, offset), HttpStatus.OK);
}
@ApiOperation(value = "게시글의 전체 건수를 반환한다. ", response = List.class)
@GetMapping(value = "/pagelink/count")
public ResponseEntity<Integer> selectBoardTotalCount() throws Exception {
logger.debug("selectBoardTotalCount - 호출");
return new ResponseEntity<Integer>(boardService.selectBoardTotalCount(), HttpStatus.OK);
}
DAO.java
// for pagination (page-link)
public List<Board> selectBoardLimitOffset(@Param("limit") int limit, @Param("offset") int offset);
public int selectBoardTotalCount();
mappers - Mybatis 를 사용하여 구현했습니다.
<!-- for vue pagination (page-link) -->
<!-- 게시글 limit offset 조회 -->
<select id="selectBoardLimitOffset" parameterType="map"
resultType="board">
select no, title, writer, content, regtime
from vue_board
limit #{limit} offset #{offset}
</select>
<!-- 게시글 limit offset 조회 -->
<select id="selectBoardTotalCount" resultType="int">
select count(*) from vue_board
</select>
반응형
'웹 프로그래밍 > Front-End' 카테고리의 다른 글
Vue.js 컴포넌트 간 Event Bus를 이용한 데이터 통신 (0) | 2020.08.16 |
---|---|
Vue + Spring Infinite Loading (Scroll) 구현 (0) | 2020.08.12 |
Vue 에서 javascript 를 이용하여 kakao login 구현 (1) | 2020.07.26 |
Vue.js - 01. 목록, 상세보기 연습 (0) | 2020.06.03 |
메모장 만들기 (1) | 2020.03.25 |