Q&A 게시판 구현하기 - Part 2 게시글 상세보기 및 페이징 처리
ㆍProject Diary/Vue (Roblox WebSite)
Q&A 게시판 구현의 두 번째 파트로, 게시글 상세보기와 페이징 처리 방법 기록
1. 게시글 상세보기 컴포넌트 (BoardDetail.vue)
게시글의 상세 내용을 표시하는 BoardDetail.vue 컴포넌트를 구현합니다.
<template>
<div class="board__detail" :class="{ dark: changeDarkMode }">
<div class="detail__title">
<h2>Q&A</h2>
</div>
<div class="go__to__list">
<router-link to="/qna" :class="{ dark: changeDarkMode }">{{
$t("[3].boarddetail.list")
}}</router-link>
</div>
<table border="1">
<colgroup>
<col />
<col />
</colgroup>
<tbody>
<tr>
<td colspan="2">
{{ $t("[3].boarddetail.title") }} {{ item.subject }}
</td>
<td colspan="1" v-if="!answerList">
{{ $t("[3].boarddetail.waiting") }}
</td>
<td colspan="1" v-else>{{ $t("[3].boarddetail.completed") }}</td>
</tr>
<tr>
<td>{{ $t("[3].boarddetail.writer") }}: {{ item.writer }}</td>
<td>{{ $t("[3].boarddetail.date") }}: {{ item.date }}</td>
<td>{{ $t("[3].boarddetail.hit") }}: {{ item.hit }}</td>
</tr>
<tr>
<td colspan="3" class="content">
<pre>{{ item.content }}</pre>
</td>
</tr>
</tbody>
</table>
<table
v-if="answerList"
class="answer__list"
:class="{ dark: changeDarkMode }"
>
<tbody>
<tr>
<td class="answer__top">
<p>{{ $t("[3].boarddetail.answer") }}</p>
<p>{{ $t("[3].boarddetail.date") }}: {{ answerList?.date }}</p>
</td>
</tr>
<tr>
<td>
<pre>{{ answerList?.answer }}</pre>
</td>
</tr>
</tbody>
</table>
<form
@submit.prevent="answerPost"
v-if="show && !answerList"
class="answer__post"
>
<p>'{{ item.subject }}'{{ $t("[3].boarddetail.reply") }}</p>
<textarea v-model="answer"></textarea>
<div class="answer__btn">
<button type="submit">{{ $t("[3].boarddetail.post") }}</button>
</div>
</form>
</div>
</template>
<script>
export default {
data() {
return {
item: null,
managerDate: "",
answer: "",
answerList: null,
managerEamil: "",
};
},
created() {
this.$store.commit("hit__Update", this.$route.params.id);
this.item = this.$store.getters.fnGetBoardList.find(
(item) => item.id === this.$route.params.id
);
this.answerList = this.$store.getters.fnGetAnswerList.find(
(item) => item.id === this.$route.params.id
);
this.managerEamil = this.$store.getters.fnGetLogined.email;
},
computed: {
show() {
if (this.managerEamil === "manager@gmail.com") {
return true;
} else {
return false;
}
},
changeDarkMode() {
return this.$store.getters.fnGetDark;
},
},
methods: {
answerPost() {
this.$store.commit("on__answer", {
answer: this.answer,
id: this.$route.params.id,
});
this.answerList = this.$store.getters.fnGetAnswerList.find(
(item) => item.id === this.$route.params.id
);
console.log(this.answerList);
},
},
};
</script>
- 1. 게시글 상세보기: created 훅에서 Vuex를 통해 현재 게시글의 상세 정보를 가져옵니다.
- 2. 답변 작성: 관리자가 로그인했을 경우, 답변 작성 폼을 표시하고, 작성된 답변을 Vuex에 저장합니다.
2. Q&A 목록 페이지 및 페이징 처리 (QnAList.vue)
Q&A 목록 페이지와 페이징 처리를 구현합니다.
<template>
<div class="qna__list">
<board-list :qnaData="qnaData" :currentPage="currentPage" />
<pagination
:totalItems="this.$store.getters.fnGetBoardList.length"
:currentPage.sync="currentPage"
:itemPerPage="itemPerPage"
/>
</div>
</template>
<script>
import BoardList from "@/components/board/BoardList.vue";
import Pagination from "@/components/layout/Pagination.vue";
export default {
data() {
return {
totalItems: [],
currentPage: 1,
itemPerPage: 10,
qnaData: [],
};
},
components: { BoardList, Pagination },
created() {
this.totalItems = JSON.parse(
JSON.stringify(this.$store.getters.fnGetBoardList)
);
for (
let i = 0;
i <
Math.ceil(this.$store.getters.fnGetBoardList.length / this.itemPerPage);
i++
) {
this.qnaData.push(this.totalItems.splice(0, 10));
}
console.log(this.qnaData);
console.log(this.$store.getters.fnGetBoardList);
},
};
</script>
<style lang="scss" scoped>
.qna__list {
max-width: 1000px;
margin: 0 auto;
}
</style>
- 1.페이징 처리: created 훅에서 전체 게시글을 페이지별로 나누어 qnaData 배열에 저장합니다.
- 2.페이지네이션 컴포넌트: pagination 컴포넌트를 사용하여 현재 페이지와 총 아이템 수를 전달합니다.
- 3.현재 페이지 상태 관리: currentPage 속성을 사용하여 현재 페이지 상태를 관리하고, 페이지가 변경될 때마다 목록을 업데이트합니다.
3. Vuex 설정 업데이트 (store/index.js 및 store/board/index.js)
페이징 처리를 위해 Vuex 설정을 업데이트합니다.
store/board/index.js
import dayjs from "dayjs";
export default {
state: {
boardList: [], // 게시글 목록 데이터
answerList: [], // 답변 목록 데이터
},
mutations: {
on__Insert(state, payload) {
let { writer, date, subject, content, status } = payload;
let id = state.boardList.length ? state.boardList[0].id + 1 : 1;
state.boardList.unshift({
id,
subject,
writer,
content,
date,
hit: 0,
status,
});
},
on__answer(state, payload) {
let date = dayjs().format("YYYY-MM-DD");
state.answerList.push({ answer: payload.answer, id: payload.id, date });
state.boardList.find((item) => item.id === payload.id).status = true;
},
hit__Update(state, payload) {
state.boardList.find((item) => item.id == payload).hit++;
},
},
getters: {
fnGetBoardList: (state) => state.boardList,
fnGetAnswerList: (state) => state.answerList,
},
};
- 1.상태 관리: state 객체에서 boardList와 answerList를 관리합니다.
- 2.변이 함수: on__Insert, on__answer, hit__Update 변이 함수를 통해 상태를 변경합니다.
- 3.게터: fnGetBoardList, fnGetAnswerList 게터를 통해 상태를 접근합니다.