이전에 Node.js 레스트 API에 카테고리, 베스트 탑을 추가하였습니다. 이번에는 Node.js 레스트 API 서버로부터 주제별 베스트 탑을 가져와 부트스크랩 카드 UI를 사용하여 리스트 위에 추가하겠습니다.
주제별 베스트 탑 가져오기
1. C:\workspaces\nodeserver\testvue\src\views\Home.vue 파일을 오픈합니다.
주제별 베스트 탑 리스트를 저장하기 위해 data에 주제별 베스트 탑 리스트(bestTopList)를 추가합니다.
data : function() {
return {
boardList : [],
boardPagination : {},
categoryList : [],
category : 0,
bestTopList : []
};
}
2. <script>의 getBestTopList() 메서드를 추가하여 Node.js 레스트 API 서버로부터 주제별 베스트 탑 리스트를 가져오게 합니다.
getBestTopList() {
this.axios.get("http://localhost:9000/boards/bestcategoryliketop").then((res)=>{
this.bestTopList = res.data.data;
}).catch((err) => {
console.log(err);
});
}
그리고 <script>의 mounted() 메서드에 getBestTopList() 메서드를 getCategoryList() 메서드 위에 추가합니다.
mounted() {
this.getBestTopList();
this.getCategoryList();
this.getBoardList(1);
}
3. Category(카테고리) UI 위에 Card(카드) UI로 주제별 베스트 탑을 추가합니다.
이전 Vue CLI 부트스크랩 5 카드(https://carrotweb.tistory.com/174), Vue CLI 부트스크랩 5 카드 말줄임(...)(https://carrotweb.tistory.com/200)를 참고하시기 바랍니다.
카드 구조와 내용을 그래도 복사하고 boardList 대신 bestTopList으로 변경합니다.
그리고 카테고리가 4개로 구성되어 있으므로 row-cols-md-3을 row-cols-md-4(가로 화면 크기가 768px보다 크거나 같으면 행(row)에 열(col)이 4개씩 배치)로 변경합니다.
<div class="pt-5">
<div class="container text-start">
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-4">
<div class="col my-2" v-for="boardItem in bestTopList" v-bind:key="boardItem.no">
<div class="card">
<img class="card-img-top" :src="(boardItem.poster.toUpperCase().startsWith('HTTP') ? '' : 'http://localhost:9000') + boardItem.poster" alt="">
<div class="card-body">
<h5 class="card-title">{{boardItem.subject}}</h5>
<h6 class="card-subtitle mb-2 text-muted">{{boardItem.writer}}</h6>
<p class="card-text">{{boardItem.content}}</p>
<div class="d-flex justify-content-between align-items-center">
<div class="btn-group">
<button type="button" class="btn btn-sm btn-outline-secondary" @click="boardNoClick(boardItem)">보기</button>
</div>
<small class="text-muted">{{boardItem.writedate}}</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
리스트 UI처럼 사용자 프로필 추가 닉네임, 작성날짜(SNS처럼 지난 시간 표시)로 변경, 보기 버튼 삭제하고 클릭 이벤트는 card에 추가 처리하겠습니다.
<div class="pt-5">
<div class="container text-start">
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-4">
<div class="col my-2" v-for="boardItem in bestTopList" v-bind:key="boardItem.no">
<div class="card" @click="boardNoClick(boardItem)">
<img class="card-img-top" :src="(boardItem.poster.toUpperCase().startsWith('HTTP') ? '' : 'http://localhost:9000') + boardItem.poster" alt="">
<div class="card-body">
<h5 class="card-title">{{boardItem.subject}}</h5>
<div class="card-subtitle my-3 list-group-item-writer">
<div class="list-group-item-writer-profile">
<img :src="(boardItem.writerProfile.toUpperCase().startsWith('HTTP') ? '' : 'http://localhost:9000') + boardItem.writerProfile" alt="">
</div>
<span>{{boardItem.writerNickname}}</span>
<small>{{elapsedText(boardItem.writedate)}}</small>
</div>
<p class="card-text">{{boardItem.content}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
카드에 라우터 링크 처리하면 카드 전체에 링크(A Tag)가 걸리게 되어 <style>에 css를 추가 처리해야 합니다. 그래서 클릭 이벤트로 처리하겠습니다.
<router-link :to="{name : 'BoardView', query : {boardNo : boardItem.no}}">
<div class="card">
<img class="card-img-top" :src="(boardItem.poster.toUpperCase().startsWith('HTTP') ? '' : 'http://localhost:9000') + boardItem.poster" alt="">
<div class="card-body">
<h5 class="card-title">{{boardItem.subject}}</h5>
<div class="card-subtitle mt-3 mb-3 list-group-item-writer">
<div class="list-group-item-writer-profile">
<img :src="(boardItem.writerProfile.toUpperCase().startsWith('HTTP') ? '' : 'http://localhost:9000') + boardItem.writerProfile" alt="">
</div>
<span>{{boardItem.writerNickname}}</span>
<small>{{elapsedText(boardItem.writedate)}}</small>
</div>
<p class="card-text">{{boardItem.content}}</p>
</div>
</div>
</router-link>
그리고 폰트와 색상도 리스트 UI와 동일하게 처리하겠습니다. 카드 CSS는 em 단위를 사용하고 있어서 카드에 폰트 크기만 설정하면 됩니다. 다만 card-title이 h5로 font-size가 1.25rem 입니다. 그래서 리스트 타이틀처럼 폰트 크기와 볼드를 추가해주면 됩니다.
.card {
font-size: 14px;
}
.card-title {
overflow: hidden;
text-overflow: ellipsis;
line-height: 1.4em;
height: 2.8em;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
font-size: 16px;
font-weight: 600; --> 추가
}
주제별 베스트 탑을 구분하기 위한 타이틀을 추가하고 <style>에 css를 추가합니다.
<div class="pt-5">
<div class="container text-start">
<div class="header">
<span class="title">주제별 BEST TOP</span>
</div>
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-4">
<div class="col my-2" v-for="boardItem in bestTopList" v-bind:key="boardItem.no">
<div class="card" @click="boardNoClick(boardItem)">
<img class="card-img-top" :src="(boardItem.poster.toUpperCase().startsWith('HTTP') ? '' : 'http://localhost:9000') + boardItem.poster" alt="">
<div class="card-body">
<h5 class="card-title">{{boardItem.subject}}</h5>
<div class="card-subtitle my-3 list-group-item-writer">
<div class="list-group-item-writer-profile">
<img :src="(boardItem.writerProfile.toUpperCase().startsWith('HTTP') ? '' : 'http://localhost:9000') + boardItem.writerProfile" alt="">
</div>
<span>{{boardItem.writerNickname}}</span>
<small>{{elapsedText(boardItem.writedate)}}</small>
</div>
<p class="card-text">{{boardItem.content}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
.header {
margin-bottom: 10px;
}
.header > .title {
font-weight: bold;
color: #000 !important;
font-size: 18px;
}
이제 블로그 사이트처럼 UI가 구성을 갖추게 되었습니다.