๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ’ก์›น ํ”„๋กœ์ ํŠธ/(ํ”„๋ก ํŠธ์—”๋“œ) ๋งˆ์ผ“์ปฌ๋ฆฌ - ํด๋ก ์ฝ”๋”ฉ

์ œํ’ˆ ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ ๊ตฌํ˜„

๊ฒ€์ƒ‰์ฐฝ์„ ์•„๋ž˜ ๋‘ ๊ณณ์— ๋‘์—ˆ๋‹ค.

  • nav์—์„œ ๊ฒ€์ƒ‰
  • SearchPage์—์„œ ๊ฒ€์ƒ‰

 

1. nav ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ

  1. nav์— ์žˆ๋Š” ๊ฒ€์ƒ‰์ฐฝ์— keyword ์ž…๋ ฅ(ํ•„์ˆ˜)
  2. ๊ฒ€์ƒ‰ ๋ฒ„ํŠผ ํด๋ฆญ 
  3. search/keyword๋กœ ์ด๋™ํ•˜๊ณ  ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์ถœ๋ ฅ

<template>
  <div id="nav">
    <div class="menu-nav">
      <div class="search-form">
        <b-form-input
          size="sm"
          class="mr-sm-2"
          type="text"
          placeholder="๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"
          v-model="keyword"  //keyword์— ๋ฐ”์ธ๋”ฉ
          @keyup.enter="searchresultshow(keyword)" //์—”ํ„ฐ ํด๋ฆญ์‹œ searchresultshow ์‹คํ–‰
        ></b-form-input>
        <b-button
          size="sm"
          class="my-2 my-sm-0"
          type="submit"
          @click="searchresultshow(keyword)" //๋ฒ„ํŠผ ํด๋ฆญ์‹œ searchresultshow ์‹คํ–‰
        >
          <b-icon icon="search"></b-icon>
        </b-button>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: "Nav",
  data() {
    return {
      keyword: ''
    }
  },
  methods: {
    searchresultshow(keyword) {
      if (keyword !== ''){ //๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•œ ๊ฒฝ์šฐ
        this.$router.push({
          name: "SearchPage",
          params: {
            keyword: this.keyword,
            isResultShow: true,
          },
        });
        this.keyword = ''
        console.log('"',keyword,'"' + ' ๊ฒ€์ƒ‰')
      } else {
        alert('๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”!')  //๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ
      }
    },
  }
};
</script>

 

2. SearchPage ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ

  1. ๊ฒ€์ƒ‰ ํŽ˜์ด์ง€์— ์žˆ๋Š” ๊ฒ€์ƒ‰์ฐฝ์— keyword ์ž…๋ ฅ(ํ•„์ˆ˜)
  2. (๊ฒ€์ƒ‰ ๋ฒ„ํŠผ ํด๋ฆญ ์ „) result ํ™”๋ฉด ์ˆจ๊ธฐ๊ธฐ
  3. (๊ฒ€์ƒ‰ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ) search/keyword๋กœ ์ด๋™ํ•˜๊ณ  ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์ถœ๋ ฅ

2-1) (์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ) SeachPage.vue

<template>
  <div id="searchpage">
    <div id="searchrequire">
      <div class="search-form-title">๊ฒ€์ƒ‰์กฐ๊ฑด</div>
      <div class="search-form-input">
        <b-form-input id="input-default" 
        type="text"
        v-model="keyword"  //keyword์— ๋ฐ”์ธ๋”ฉ
        v-on:input="keywordChanged()"
        v-on:keyup.enter="searchresultshow(keyword)"
        >
        {{keyword}} //nav.vue์—์„œ ๋ผ์šฐํ„ฐ๋ฅผ ์ด์šฉํ•ด ๋ณด๋‚ธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ ๋ฐ›์Œ 
        </b-form-input>
      </div>
      <div class="search-form-button">
        <button @click="searchresultshow(keyword)">
          ๊ฒ€์ƒ‰
        </button>
      </div>
    </div>
    <SearchResult v-if="isResultShow" v-bind:keyword="keyword"></SearchResult>  //ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ์— ๋ฐ์ดํ„ฐ ์ „๋‹ฌ
    <div v-else>
      ์•„์ง ๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.
    </div>
  </div>
</template>
<script>
import SearchResult from "@/components/SearchResult.vue";

export default {
  name: "SearchPage",
  components: {
    SearchResult
  },
  data() {
    return {
      isResultShow:true,  //nav.vue์—์„œ ๋ผ์šฐํ„ฐ๋ฅผ ์ด์šฉํ•ด ๋ณด๋‚ธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ ๋ฐ›์Œ 
      keyword: this.$route.params.keyword  //nav.vue์—์„œ ๋ผ์šฐํ„ฐ๋ฅผ ์ด์šฉํ•ด ๋ณด๋‚ธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ ๋ฐ›์Œ 
    }
  },
  methods: {
    searchresultshow(keyword) {
      console.log('"',keyword,'"' + ' ๊ฒ€์ƒ‰')
      if (keyword !== ''){
        this.$router.push({
          name: "SearchPage",
          params: {
            keyword: this.keyword
          },
        }).catch(()=>{});
        this.isResultShow = true
      } else {
        alert('๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”!')
      }
    },
    keywordChanged() {
      this.isResultShow = false
    }
  }
};
</script>

 

2-2) (ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ) SearchResult.vue

<template>
  <div id="searchresult">
    <div class="result-title">
      ์ด {{$store.getters.getFilteredProduct(keyword).length}}๊ฐœ์˜ ์ƒํ’ˆ์ด ๊ฒ€์ƒ‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
    </div>
    
    <div class="result-items">
      <div
      class="resultitem"
      :key="index"
      v-for="(product, index) in $store.getters.getFilteredProduct(keyword)"
      @click="detailshow(index)"
    >
      <div class="product-img">
        <img v-bind:src="product.productimg" />
      </div>
      <div class="product-info">
        <li class="product-info-title">{{ product.title }}</li>
        <li class="product-info-price">{{ product.price }}์›</li>
      </div>
    </div>
    </div>
  </div>
</template>
<script>
export default {
  name: "SearchResult",
  props: [ 'keyword'], //์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์ธ SearchPage.vue๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ ๋ฐ›์Œ
  data() {
    return {
    }
  },
  methods: {}
}
</script>

 

2-3) ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” getter์ถ”๊ฐ€ (store/index.js)

getters: {
    getFilteredProduct:(state) => (keyword) => {
        const filtered = state.products.filter((object) => 
          object.title.toLowerCase().includes(keyword.toLowerCase()) || 
          object.description.toLowerCase().includes(keyword.toLowerCase()
        ));
        if (filtered) return filtered;
    },
},