반응형

이전까지 진행 상황

[Node.js + Vue.js] 게시판 만들기 1. 설계 & 결과
[Node.js + Vue.js] 게시판 만들기 2. Vue.js를 사용한 Front Server 구현
[Node.js + Vue.js] 게시판 만들기 3. Node.js를 사용한 Back Server 구현

추가 기능 정리

  • 메인화면에 검색기능 추가
  • 제목검색, 작성자검색 가능하고 키워드를 포함하는 게시물 모두 불러옴
  • 게시글 클릭시 해당 게시글 페이지로 이동
  • 검색결과가 총 몇개인지 표시
  • 게시판 페이지에서 구현했었던 10개씩 불러오는 기능은 구현하지 않음 ( 한 페이지에 모두 나타남 )

추가 코드

Front -> Main.vue template 부분 추가코드

<v-row :style="{marginTop: '50px'}">
    <v-col cols="12" md="2" />
    <v-col cols="12" md="2">
        <v-select
              :items="searchoption"
              v-model="searchoptionselected"
              :style="{width:'90px', marginLeft:'90px'}" />
    </v-col>
    <v-col cols="12" md="4">
        <v-text-field v-model="searchkeyword" dense outlined label="검색키워드" 
        full-width :style="{marginTop:'10px'}"/>
    </v-col>
    <v-col cols="12" md="1">
        <v-btn @click="searchstart" :style="{marginTop:'10px'}">검색</v-btn>
    </v-col>
    <v-col cols="12" md="3" />
</v-row>
<v-row v-if="searchfinish===true" :style="{marginTop:'0px'}">
    <v-col cols="12" md="5"/>
    <v-col cols="12" md="2">
        <div style="font-size: x-large">검색결과 : {{searchcnt}} 개</div>
    </v-col>
    <v-col cols="12" md="5"/>
</v-row>
<!-- 여기서부터는 게시판 페이지와 거의 일치, 검색완료시에만 표가 나타나게 했고, 게시판 번호 표시 -->
<v-row v-if="searchfinish===true">
    <v-simple-table style="width: 100%;">
        <thead>
            <tr style="font-weight: bolder;">
                <td style="width:10%; font-size: x-large;">게시판</td>
                <td style="width:20%; font-size: x-large;">작성자</td>
                <td style="width:50%; font-size: x-large;">제목</td>
                <td style="width:20%; font-size: x-large;">작성일</td>
            </tr>
        </thead>
        <tbody>
            <tr v-for="item in contentlist" :key="item.id" @click="movetocontent(item.boardnum, item.id)">
                <td>{{item.boardnum}}</td>
                <td>{{item.writer}}</td>
                <td>{{item.title}}</td>
                <td>{{item.createdAt.split('T')[0]}}</td>
            </tr>
        </tbody>
    </v-simple-table>
</v-row>
  • 원래 있던 3개의 버튼 밑에 추가
<v-footer min-height="50px" color="white"/>
  • 검색된 게시물이 많아 스크롤이 생겼을 때, 가장 아래부분에 빈칸이 없어져서 다음에 v-footer을 추가

Front -> Main.vue script 부분 추가코드

import axios from 'axios'
  • 메인화면에서도 게시글 불러오려면 axios 필요
// data 속성 전체 코드
data() {
    return {
      searchkeyword: '',        // 검색키워드
      searchfinish: false,        // 검색완료시 true로 바뀌고, 이때부터 표 생성
      searchoption: ['제목','작성자'],    // 검색옵션
      searchoptionselected: '제목',    // 검색옵션값 받아오기, 기본값은 제목으로 지정
      searchcnt: 0,            // 검색된 게시글 갯수
      contentlist: [],            // 게시글 리스트
    }
  },
// method 속성 추가 코드
movetocontent(boardnum, id) {    // 검색된 게시글 클릭시 해당 게시글로 이동
    window.location.href = 'http://127.0.0.1:8080/board/' + boardnum + '/content?id=' + id
},
searchstart(){            // 검색버튼 눌렀을때 실행
    if(this.searchkeyword == '') {
        alert('키워드가 없습니다!');
    } else {
        axios({
            url: "http://127.0.0.1:52273/content/search/",
              method: "POST",
              data: {        // 선택된 검색옵션과 검색키워드 넘겨줌
                searchoption: this.searchoptionselected,
                searchkeyword: this.searchkeyword,
              },
        }).then(res => {
            this.contentlist = res.data;
            this.searchcnt = this.contentlist[Object.keys(this.contentlist).length-1].cnt;
            this.contentlist.pop();
            alert('검색완료!');
            this.searchfinish = true;
            this.searchkeyword = '';
        }).catch(err => {
          alert(err);
        });
      }
    },

Back -> routes/content.js 추가코드

var Op = require('sequelize').Op;
  • Sequelize에서 특정단어를 포함하는 검색기능 사용할 때 sequelize.Op 필요
router.post('/search', function(req, res){
    if(req.body.searchoption == '제목'){    // searchoption이 '제목'일 때
        db.content.findAndCountAll({
            where: {
                title: {
                    [Op.like]: "%"+req.body.searchkeyword+"%"
                    // "%" + [단어] + "%"를 통해 [단어]가 포함된 모든것 검색 가능
                },
            },
            order: [['id', 'ASC']],
            raw: true,
        }).then(result => {
            var cnt = new Object();
            cnt.cnt = result.count;
            result.rows.push(cnt);
            console.log(result.rows);
            return res.status(200).json(result.rows);
        }).catch(err => {
            console.log(err);
            return res.status(404).json({message: '에러뜸'});
        })
    } else {    // searchoption이 '작성자'일 때
        db.content.findAndCountAll({
            where: {
                writer: {
                    [Op.like]: "%"+req.body.searchkeyword+"%"
                },
            },
            order: [['id', 'ASC']],
            raw: true,
        }).then(result => {
            var cnt = new Object();
            cnt.cnt = result.count;
            result.rows.push(cnt);
            console.log(result.rows);
            return res.status(200).json(result.rows);
        }).catch(err => {
            console.log(err);
            return res.status(404).json({message: '에러뜸'});
        })
    }
});

결과

검색창이 추가된 메인 페이지

제목에 1이 들어간 게시물 검색

검색 결과

반응형

↓ 클릭시 이동

복사했습니다!