[Vue.js] 실시간 검색 구현하기 (버튼, 엔터 필요없다)

Yeonsu Summer·2022년 10월 17일
2

Vue.js

목록 보기
6/6
post-thumbnail

웹사이트를 사용하면서 정말 편리한 기능을 발견해서 저도 똑같은 기능을 구현해보았습니다.

그것은 바로 버튼 없이, 엔터 없이, 실시간으로 검색하는 것 입니다.

시작 전에 필요한 것은 Vue와 JS를 간단히 알기^^, JSON 데이터 입니다.

JSON 데이터를 가져오는 방법은 아래 링크를 참고해주세요!

⬇⬇⬇

https://velog.io/@yeonsubaek/Vue.js-Vue%EC%97%90%EC%84%9C-JSON-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0

⬆⬆⬆

우선, 간단한 html과 css작업, JSON 연결을 해줍니다.

assets/group.json

[
  {
    "name": "아이브",
    "debut": "2021",
    "member": "6"
  },
  {
    "name": "스테이씨",
    "debut": "2020",
    "member": "6"
  },
  {
    "name": "뉴진스",
    "debut": "2022",
    "member": "5"
  },
  {
    "name": "에스파",
    "debut": "2020",
    "member": "4"
  },
  {
    "name": "엔믹스",
    "debut": "2022",
    "member": "7"
  },
  {
    "name": "르세라핌",
    "debut": "2022",
    "member": "5"
  }
]

app.vue

<template>
  <div>
    <input
      class="search-input"
      type="text"
      placeholder="그룹명, 데뷔년도, 멤버수를 입력하세요"
    />

    <ul class="group-list">
      <li class="group-list-header">
        <span>그룹명</span>
        <span>데뷔년도</span>
        <span>멤버수</span>
      </li>
      <li v-for="group in groupList" :key="group" class="group-item">
        <span>{{ group.name }}</span>
        <span>{{ group.debut }}</span>
        <span>{{ group.member }}</span>
      </li>
    </ul>
  </div>
</template>

<script>
import data from "@/assets/group.json";

const groupList = data;

export default {
  data() {
    return {
      groupList,
    };
  }
}
</script>

<style>
* {
  padding: 0;
  margin: 0;
}
.search-input {
  display: block;
  padding: 4px 8px;
  margin: 10px auto;
  width: 320px;
  font-size: 16px;
  outline: none;
}

.group-list {
  margin: 0 auto;
  width: 360px;
}

.group-list li {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 32px;
  list-style-type: none;
}

.group-list span {
  display: block;
  width: 33%;
  text-align: center;
}

.group-list-header {
  font-weight: 700;
  border-bottom: 1px solid #bdbdbd;
}
</style>

검색창에 입력을 해도 아무런 동작이 되지 않는 정적이 화면이 완성되었습니다.

우리가 만들 기능은 실시간으로 검색어를 입력 받고 동일한 문자열을 지닌 데이터만 보여주는 것 입니다.

searchGroup 함수를 추가해봅시다.

<template>
  <div>
    <input
      class="search-input"
      type="text"
      placeholder="그룹명, 데뷔년도, 멤버수를 입력하세요"
      @input="searchGroup($event)"
    />

    <!-- 위와 동일 -->
  </div>
</template>

<script>
import data from "@/assets/group.json";

const groupList = data;

export default {
  data() {
    return {
      groupList,
    };
  },

  methods: {
    searchGroup(event) {
      // console.log(event.target.value);
    
      const len = this.groupList.length;

      for (let i = 0; i < len; i++) {
        if (
          this.groupList[i].name.includes(event.target.value) === false &&
          this.groupList[i].debut.includes(event.target.value) === false &&
          this.groupList[i].member.includes(event.target.value) === false
        ) {
          document.querySelectorAll(".group-item")[i].style.display = "none";
        } else {
          document.querySelectorAll(".group-item")[i].style.display = "flex";
        }
      }
    },
  },
};
</script>

<style>
/* 위와 동일 */
</style>

함수 하나만 추가하면 완성이 됩니다.

input 안에 @input="searchGroup($event)"를 넣습니다. $event란 ... 제가 한마디로 설명하기에 100프로 이해는 못했지만 키보드 입력을 받을 때 사용합니다! (더 자세히 공부를 해야겠어요...)

searchGroup 함수에는 name, debut, member 어디에도 입력 받은 값이 존재하지 않으면 해당 .group-item을 숨기는 기능을 넣어야 합니다.

모든 .group-item에 적용하기 위해서 반복문을 사용하였습니다. 이때 반복 횟수만큼 매번 array.length 속성을 참조하는 것이 비효율적이기 때문에

const len = this.groupList.length;

으로 다시 선언하였습니다.

조건문을 사용해서 '세가지 값 어디에도 입력 값이 존재하지 않다면''그렇지 않으면(셋 중 하나라도 존재하면)'으로 나누어 생각하였습니다.
문자열 포함 여부를 알기 위해서 includes() 함수를 사용하였습니다. 입력값은 event.target.value 로 알 수 있습니다.

console.log(event.target.value);

위 콘솔 명령을 입력하시면 키보드가 눌린 대로 콘솔에 작성된 것을 확인할 수 있습니다.

전체 코드

<template>
  <div>
    <input
      class="search-input"
      type="text"
      placeholder="그룹명, 데뷔년도, 멤버수를 입력하세요"
      @input="searchGroup($event)"
    />

    <ul class="group-list">
      <li class="group-list-header">
        <span>그룹명</span>
        <span>데뷔년도</span>
        <span>멤버수</span>
      </li>
      <li v-for="group in groupList" :key="group" class="group-item">
        <span>{{ group.name }}</span>
        <span>{{ group.debut }}</span>
        <span>{{ group.member }}</span>
      </li>
    </ul>
  </div>
</template>

<script>
import data from "@/assets/group.json";

const groupList = data;

export default {
  data() {
    return {
      groupList,
    };
  },

  methods: {
    searchGroup(event) {
      const len = this.groupList.length;

      for (let i = 0; i < len; i++) {
        if (
          this.groupList[i].name.includes(event.target.value) === false &&
          this.groupList[i].debut.includes(event.target.value) === false &&
          this.groupList[i].member.includes(event.target.value) === false
        ) {
          document.querySelectorAll(".group-item")[i].style.display = "none";
        } else {
          document.querySelectorAll(".group-item")[i].style.display = "flex";
        }
      }
    },
  },
};
</script>

<style>
* {
  padding: 0;
  margin: 0;
}
.search-input {
  display: block;
  padding: 4px 8px;
  margin: 10px auto;
  width: 320px;
  font-size: 16px;
  outline: none;
}

.group-list {
  margin: 0 auto;
  width: 360px;
}

.group-list li {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 32px;
  list-style-type: none;
}

.group-list span {
  display: block;
  width: 33%;
  text-align: center;
}

.group-list-header {
  font-weight: 700;
  border-bottom: 1px solid #bdbdbd;
}
</style>

결과

ex 1ex 2ex 3
profile
🍀 an evenful day, life, journey

0개의 댓글