티스토리 뷰

 

>>>

검색 옵션) 1. 책 제목   2. 책 저자   3. isbn (IoT에서 비전 인식으로 받아온 바코드 값으로 검색 가능)

: 검색 옵션에 맞게 DB에 있는 값과 검색어를 비교하여 일치하는 책 리스트를 출력한다.

 

[결과]

1.메인화면 

 

2. 저자 검색, isbn 검색

3. 제목검색 : '이'가 포함된 모든 책이 나열된다.

 


[구현 ]

A. Front

  1. home.vue

  웹 페이지에서 실행되고 보여지는 것.

    <b-container id="search-section" fluid>
      <!-- search section -->
      <b-input-group>
        <template #prepend>
          <b-form-select v-model="selectSearch" text="검색 옵션" variant="light" :options="select"> </b-form-select>
        </template>

        <b-form-input
          v-model="searchInput"
          :placeholder="`검색할 도서의 ${selectSearch == 'title' ? '제목' : '저자'}명을 입력해주세요.`"
        ></b-form-input>

        <template #append>
          <!-- <b-button variant="primary" @click="searchStorageList(searchInput)">검색</b-button> -->
          <b-button variant="primary" @click="onClickSearch(searchInput)">검색</b-button>
        </template>
      </b-input-group>
    </b-container>

    이 부분이 [ 검색 옵션 : ____입력 바_____ : 검색 버튼 ] 을 그려주는 HTML이다.

    뷰 부트스트랩을 이용하여 팀원 분이 작성해 주셨다. https://bootstrap-vue.org/docs/components/modal#modals

    여기서 중요한 부분은 v-model , :options , @click="onClickSearch(searchInput)" 이 세가지이다.!!

<script>
export default {
  data() {
    return {
      fields: [
        { key: 'id', label: 'id' },
        { key: 'isbn', label: 'ISBN' },
        { key: 'title', label: '제목' },
        { key: 'author', label: '저자' },
        { key: 'publisher', label: '출판사' },
        { key: 'review', label: '리뷰' },
        { key: 'link', label: '링크' },
        { key: 'location', label: '도서위치' },
        { key: 'price', label: '가격' },
        { key: 'createdAt', label: '생성일' },
        { key: 'updateBtn', label: '수정' },
        { key: 'deleteBtn', label: '삭제' }
      ],
      // 제목 & 저자명 search 위한 변수들입니다.
      select: [
        { text: '제목', value: 'title' },
        { text: 'ISBN', value: 'isbn' },
        { text: '저자', value: 'author' }
      ],
      selectSearch: 'title', //검색 옵션 : 제목검색
      searchInput: null, //검색어
      isMQTT: false, // mqtt에서 보낸값인가?
      mtopic: 'rasp/1', //토픽 설정
      mqttDataList: [] // mqtt를 통해 받은 데이터(리스트로 계속 추가됨)
    }
  },
 
 ...
   ,methods: {
    init() {
      console.log('처음페이지')
      // 2. 리스트 재검색
      this.searchStorageList()
    },
    onClickSearch(searchInput) {
      console.log(this.selectSearch)
      //검색하기
      if (!this.isMQTT) {
        if (this.selectSearch === 'title') {
          this.$store.dispatch('actStorageInfo', { title: searchInput })
        }
        if (this.selectSearch === 'author') {
          this.$store.dispatch('actStorageInfo', { author: searchInput })
        }
        if (this.selectSearch === 'isbn') {
          this.$store.dispatch('actStorageInfo', { isbn: searchInput })
        }
      } else {
        //isMQTT = true
        this.$store.dispatch('actStorageInfo', { isbn: searchInput })
        this.isMQTT = false
      }
      // 2. 리스트 재검색
      // this.searchStorageList()
    },
    
    ...
  
  </script>

    아래 스크립트 data() 부분에 이렇게 변수를 설정해줄 수 있는데

    selectSearch는 선택된 옵션값이고 초기 값으로 title을 지정해 줬다.

    option 은 선택 옵션에서 선택할 수 있는 제목, 저자, isbn 값을 넣어주었다.

    methods : 부분에 함수를 넣어줄 수 있다. 클릭 했을 떄 @로 onclickseach함수를 호출해주었고

    인자 값으로 사용자가 입력한 값을 보내준다.

    함수를 살펴보면 여기서$store가 사용된 것을 알수 있다.

    

  2. store

  : Axios를 통해 백엔드의 DB와 통신하여 데이터를 관리하는 폴더. 

    a. api 호출

       엑시오스 연결은 다른 파일에서 관리하고 이렇게 불러와 "api"로 사용한다.

>store > apiUtil.js

import axios from 'axios'

const api = axios.create()

export default api

>sotre > model > storage.js

import api from '../apiUtil'

       스토어의 구조는 이렇다.

       state가 요리 결과, getter가 제공, mutation 운반, action 요리하기 라고 생각하면 이해가 ... 될 것이다.

      따라서 아까  함수에서 스토어 호출한 부분을 봐보자.

 onClickSearch(searchInput) {
      console.log(this.selectSearch)
      //검색하기
      if (!this.isMQTT) {
        if (this.selectSearch === 'title') {
          this.$store.dispatch('actStorageInfo', { title: searchInput })
        }
        if (this.selectSearch === 'author') {
          this.$store.dispatch('actStorageInfo', { author: searchInput })
        }
        if (this.selectSearch === 'isbn') {
          this.$store.dispatch('actStorageInfo', { isbn: searchInput })
        }
      } else {
        //isMQTT = true
        this.$store.dispatch('actStorageInfo', { isbn: searchInput })
        this.isMQTT = false
      }
      // 2. 리스트 재검색
      // this.searchStorageList()
    },
 onClickSearch(searchInput) {
\...
          this.$store.dispatch('actStorageInfo', { isbn: searchInput })
\...
}

       구체적으로는 이 부분 ! 스토어에서 actions 부분을 실행하려면 this.$store.dispatch로 호출한다. 

       "actStorageInfo" 이부분이 액션의 이름과 일치해야 실행되고 인자로 { isbn(검색옵션): 입력된 검색 값 }을 묶어서 보낸다.

       그러면 액션의 'actStorageInfo'부분이 실행된다.

// 중고도서 상세정보 조회 검색
    actStorageInfo(context, payload) {
      // 상태값 초기화
      context.commit('setStorage', { ...stateInit.Storage })

      // RestAPI 호출
      if (payload !== undefined) {
        let _option = Object.keys(payload)[0]
        let _value = payload[Object.keys(payload)[0]]
        console.log('store검색 입력값, option:', _option)
        console.log('store검색 입력값, value:', _value)
        api
          .get(`/serverApi/home/${_option}/${_value}`)
          .then(response => {
            const storage = response && response.data
            context.commit('setStorageList', storage.rows) // 리스트에 넣는다.
            console.log('store검색 결과', storage.rows) // 책 하나의 정보들
          })
          .catch(err => {
            console.error(err)
          })
      }
    },

       api.get로 엑시오스를 통해 백엔드 서버에 주소와 값을 조회할 수 있다.

      참고로 post 는 값 보내기 (주소,인자), put은 수정 delete는 삭제다.

      값을 받아오면 .then 이 실행되고 그 값은 response에 저장되고,

      context.commit 메소드로 setStorageList(set이 붙은 애들은 mutations 운반체)에 storage.rows 값을 넣을 수 있다.

      const storage 변수를 설정해 여기에 받아온 값을 담았다  &&를 사용하면 그 값이 있으면 ~ 처럼 if 같이 사용할 수 있다.

      storageList는 home.vue에서 계속 지켜보고있고 값이 변하면 리스트를 다시 출력하게 되어있어서 바로 출력이 된다.

>home.vue

(Script 부분)

computed 값이 변하면 return값을 반환함 -> 바로 프론트에 업데이트 됨.

    **$store.getters(요리 제공) StorageList에 있는 값을 받아올 수 있다.

watch: 값이 변화하면 실행할 것들 적을 수 있음.

(HTML부분)

   <!-- book list section -->
    <b-container id="card-section" fluid>
      <b-card-group deck>
        <b-card
          v-for="item in storageList"
          :key="item.id"
          :title="item.title"
          :img-src="item.image"
          img-alt="Image"
          img-top

: 여기서 중요한것은 itme in storageList  

compute에서 계속해서 변화를 인식하고있는 storageeList를 for문을 돌려 전부 리스트로 표시한다.

:값 아래 data()에 선언된 변수와 연동된다 item은 책 오브젝트를 말한다.


B. Backend

api 부분에서 백이랑 연결되는 부분을 살펴보자.

(front)

>store > model > storage.js

        api
          .get(`/serverApi/home/${_option}/${_value}`)
          .then(response => {
            const storage = response && response.data
            context.commit('setStorageList', storage.rows) // 리스트에 넣는다.
          })
          .catch(err => {
            console.error(err)
          })

: get 받아온다 '주소'에 있는 값을 .then 받아온 값을 setStorageList에 넣어준다.

: 보내는 값 : _option 은 검색옵션 , _value는 검색 입력 값을 주소에 담는다 !!!

  1. routes

:익스프레스 패키지를 활용하여 코드를 단순하게 한다.

>routes>home.js

const express = require('express');
const router = express.Router();
const storageService = require('../service/storageService');

 (검색 옵션에 따라 주소를 다르게 적용했다.)

//제목 검색기능 상세정보 조회
router.get('/title/:title', async (req, res) => {
  try {
    const params = { 
      title: req.params.title,
      author: req.params.author, 
      isbn: req.params.isbn, 
    }

    const result = await storageService.search(params)

    // 최종 응답
    res.status(200).json(result);
  } catch (err) {
    res.status(500).json({ err: err.toString() });
  }
})
//저자 검색기능 상세정보 조회
router.get('/author/:author', async (req, res) => {
  try {
    const params = { 
      title: req.params.title,
      author: req.params.author, 
      isbn: req.params.isbn, 
    }

    const result = await storageService.search(params)

    // 최종 응답
    res.status(200).json(result);
  } catch (err) {
    res.status(500).json({ err: err.toString() });
  }
})
//제목 검색기능 상세정보 조회
router.get('/isbn/:isbn', async (req, res) => {
  try {
    const params = { 
      title: req.params.title,
      author: req.params.author, 
      isbn: req.params.isbn, 
    }

    const result = await storageService.search(params)

    // 최종 응답
    res.status(200).json(result);
  } catch (err) {
    res.status(500).json({ err: err.toString() });
  }
})

받아온 값을 보면 검색 옵션 title , 입력된 검색 값 : 병주 이런식이다.

/title/:title로 이동된다.

여기서 중요한 부분은 

    const result = await storageService.search(params)

 req 값으로 받아온 값 : 병주 를 params에 담아 storageService에 보낸다 . 

  2. storageService

     실행을 처리하는 부분 dao랑 연결된다.

     dao는 DB와 sequelize로 연결되며 postgreSQL과 연결되어 데이터 베이스의 값들을 수정 추가 삭제한다.

const storageDao = require('../dao/storageDao');

  // selectList 리스트 불러오기
  async list(params) {
    let result = null;
    try {
      result = await storageDao.selectList(params);
    } catch (err) {
      return new Promise((resolve, reject) => {
        reject(err);
      });
    }
    return new Promise((resolve) => {
      resolve(result);
    });
  },

dao와 소통하며 dao에서 받아온 값을 라우터로 보내준다.

** result = await storageDao.selectList(params)

 

  3. dao

const { Op } = require('sequelize');
const { Storage } = require('../models/index');

...

// 리스트 조회
  selectList(params) {
    // where 검색 조건 - title
    const setQuery = {};
    if (params.title) {
      setQuery.where = {
        ...setQuery.where,
        title: { [Op.like]: `%${params.title}%` }, // like검색
      };
    }
    // where 검색 조건 - author
    if (params.author) {
      setQuery.where = {
        ...setQuery.where,
        author: { [Op.like]: `%${params.author}%` }, // like검색
      };
    }
    // where 검색 조건 - isbn
    if (params.isbn) {
      setQuery.where = {
        ...setQuery.where,
        isbn: { [Op.like]: `%${params.isbn}%` }, // like검색
      };
    // order by 정렬 조건
    setQuery.order = [['id', 'DESC']];
    //결국 전달하는 건 이 부분이다.
    return new Promise((resolve, reject) => {
       Storage.findAndCountAll({
         ...setQuery,
      //전체를 전달한다.
       }).then((selectedList) => {
        resolve(selectedList)
      }).catch((err) => {
        reject(err);
      });
    });

      검색 조건에 따라 DB(sequelize로 연결된 postgreSQL)의 테이블을 검색하고,

      params에 받아온 입력된 검색 단어를 like 검색(where)하여  setQuery에 담는다.

     return 부분에서 strage에 값을 담아 보낸다 !!!!!!!!!!!

    결과 값 dao ->storageService -> router/home : 프론트에서 접속한 주소로 결과 값이 이동되어 다시 프론트로 전송된다 !!!

 

프론트에서 response 부분이 StorageList에 저장되고 compute 부분에서 이 변화를 계속 감지하여 리스트로 표시되게 한다 !!!

 

'Web > Front - Vue' 카테고리의 다른 글

vue / webpack / three.js  (0) 2022.08.21
Front_JS_객체의 첫 번째 키 or 값 출력하기  (0) 2022.04.22
Vue_기본함수,기능  (0) 2022.03.22
Vue_router설정  (0) 2022.03.22
Vue_create 오류  (0) 2022.02.15
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함