
1. SearchBar.vue 만들기

2. 검색창 기본 틀 만들기
<template> <div> <p>searchBar</p> </div> </template> <script> export default { name: "SearchBarComponent" } </script> <style> </style>
3. 컴포넌트 등록하고 화면에 표시하기
<template> <div> <Navbar /> <Event :text="text" /> <searchBar /> <Movies :movies="movies" @openModal="isModal=true; selectedMovie=$even" @incrementLike="incrementLike($event)" /> <!-- 자식에게 변수 값 전달하기 --> <Modal :movies="movies" :isModal="isModal" :selectedMovie="selectedMovie" @closeModal="isModal=false" /> </div> </template> <script> import movies from './assets/movies'; import Navbar from './components/Navbar.vue'; import Modal from './components/Modal.vue'; import Movies from './components/Movies.vue'; import Event from './components/Event.vue'; import SearchBar from './components/SearchBar.vue'; export default { name: 'App', data() { return { isModal: false, selectedMovie: null, movies: movies, text: "Neplix 강렬한 운명의 드라마, 경기크리처" } }, methods: { incrementLike(i) { this.movies[i].like++; }, selectMovie(i) { this.selectedMovie = i; this.isModal = true; }, }, components: { Navbar: Navbar, Modal: Modal, Movies: Movies, Event: Event, searchBar: SearchBar } } </script>
4. 검색 바 만들기
- 타입은 text or search
- 검색창에 입력받은 데이터 사용하기
- 사용자가 입력할때 ` $event.target.value` 값으로 들어옴 / JS 문법과 동일
<template> <div class="search-box"> <input type="search" @input="inputText = $event.target.value"> </div> <p>{{ inputText }}</p> <!--받은 값 확인하기--> </template> <script> export default { name: "SearchBarComponent", data() { return { inputText: '', } } } </script> <style> </style>


5. CSS 적용하기
- plaeholder 추가하기
<template> <div class="search-box"> <input type="search" @input="inputText = $event.target.value" placeholder="검색어를 입력해주세요"> <button>🔍</button> </div> <p>{{ inputText }}</p> <!--받은 값 확인하기--> </template> <script> export default { name: "SearchBarComponent", data() { return { inputText: '', } } } </script> <style> .search-box { padding: 10px; display: flex; justify-content: center; } .search-box input { padding: 5px 10px; } .search-box button { margin: 0; } </style>

6. 검색 결과 감지하기
- v-model은 편하지만 글자를 하나하나 입력할 때마다 감지됨
// 같은 결과 @input="inputText = $event.target.value" v-model="inputText"
- watch : 검사할 항목
검사할 변수명(변경된 값, 이전 값)
<template> <div class="search-box"> <input type="search" v-model="inputText" placeholder="검색어를 입력해주세요"> <button>🔍</button> </div> <p>{{ inputText }}</p> <!--받은 값 확인하기--> </template> <script> export default { name: "SearchBarComponent", data() { return { inputText: '', } }, watch: { // 검사할 항목 inputText(name) { // 검사할 변수명(변경된 값, 이전 값) //입력한 영화제목이 데이터에 있는지 확인하기 if(name != "에일리언"){ alert('해당하는 영화가 없습니다'); } } } } </script>

- 입력이 완료된 후 감지되어야 함
@change="inputText = $event.target.value" // 입력 후 포커스가 벗어나거나 엔터를 눌렀을 때 감지
<template> <div class="search-box"> <input type="search" @change="handleChange" placeholder="검색어를 입력해주세요"> <button>🔍</button> </div> <p>{{ inputText }}</p> <!--받은 값 확인하기--> </template>


7. 자료 탐색하기
- JS의 filter : 조건과 일치하는 값이 있으면 해당 값을 반환해줌
const foods = ['apple', 'banana', 'mango']; const findFood = foods.filter(food => { return food === "banana"; }) console.log(findFood);

- 영화 데이터 넘겨주기
<template> <div> <Navbar /> <Event :text="text" /> <SearchBar :movies="movies"/> <!--영화 데이터 넘겨주기--> <Movies :movies="movies" @openModal="isModal=true; selectedMovie=$even" @incrementLike="incrementLike($event)" /> <!-- 자식에게 변수 값 전달하기 --> <Modal :movies="movies" :isModal="isModal" :selectedMovie="selectedMovie" @closeModal="isModal=false" /> </div> </template>
- filter 사용하기
<script> export default { name: "SearchBarComponent", data() { return { inputText: '', } }, props: { movies: Array, }, watch: { inputText(name) { // 입력한 영화 제목이 데이터에 있는지 확인하 const findName = this.movies.filter(movie => { return movie.title.includes(name); }) console.log(findName); } } } </script>


- 결과가 없을 경우
- alert창 띄워서 알리기
<script> export default { name: "SearchBarComponent", data() { return { inputText: '', } }, props: { movies: Array, }, watch: { inputText(name) { // 입력한 영화 제목이 데이터에 있는지 확인하기 const findName = this.movies.filter(movie => { return movie.title.includes(name); }) if(findName.length == 0) { alert('해당하는 영화가 없습니다'); } } } } </script>

8. 검색후 자동으로 비우고 검색하기
- 검색후 커스텀 이벤트로 inputText 비워주기
- watch는 데이터가 변경되는 시점에 적용됨
<template> <div> <div class="search-box"> <input type="search" @change="inputText = $event.target.value; $event.target.value = ''" placeholder="검색어를 입력해주세요"> <button>🔍</button> </div> </div> </template>



9. 검색 결과만 화면에 띄우기
- 영화 정보를 가져오는 사본 데이터를 만들어서 필요한 결과만 보여주기
- 변수를 만들어 저장하고 복사본을 사용해야 원본 데이터로 돌아갈 수 있음
- 복사본 만들기
<script> import movies from './assets/movies'; import Navbar from './components/Navbar.vue'; import Modal from './components/Modal.vue'; import Movies from './components/Movies.vue'; import Event from './components/Event.vue'; import SearchBar from './components/SearchBar.vue'; export default { name: 'App', data() { return { isModal: false, selectedMovie: null, movies: movies, // 원본 데이터 movies_temp: [...movies], // 사본 데이터 text: "Neplix 강렬한 운명의 드라마, 경기크리처" } }, methods: { incrementLike(i) { this.movies[i].like++; }, selectMovie(i) { this.selectedMovie = i; this.isModal = true; }, }, components: { Navbar: Navbar, Modal: Modal, Movies: Movies, Event: Event, SearchBar: SearchBar } } </script>
- 부모에게 데이터 전달하기
<template> <div> <div class="search-box"> <input type="search" @change="$emit('searchMovie', $event.target.value) // 데이터 전달 inputText = $event.target.value; $event.target.value = ''" placeholder="검색어를 입력해주세요"> <button>🔍</button> </div> </div> </template>
- searchMovie라는 메서드를 만들어서 검색 결과 전달하기
<template> <div> <Navbar /> <Event :text="text" /> <SearchBar :movies="movies_temp" @searchMovie="searchMovie($event)"/> <!--영화 데이터 넘겨주기--> <Movies :movies="movies_temp" @openModal="isModal=true; selectedMovie=$even" @incrementLike="incrementLike($event)" /> <!-- 자식에게 변수 값 전달하기 --> <Modal :movies="movies_temp" :isModal="isModal" :selectedMovie="selectedMovie" @closeModal="isModal=false" /> </div> </template> <script> import movies from './assets/movies'; import Navbar from './components/Navbar.vue'; import Modal from './components/Modal.vue'; import Movies from './components/Movies.vue'; import Event from './components/Event.vue'; import SearchBar from './components/SearchBar.vue'; export default { name: 'App', data() { return { isModal: false, selectedMovie: null, movies: movies, // 원본 데이터 movies_temp: [...movies], // 사본 데이터 text: "Neplix 강렬한 운명의 드라마, 경기크리처" } }, methods: { incrementLike(i) { this.movies[i].like++; }, selectMovie(i) { this.selectedMovie = i; this.isModal = true; }, searchMovie(title) { // 영화 제목이 포함된 데이터 this.movies_temp = this.movies.filter(movie => { return movie.title.includes(title); }) } }, components: { Navbar: Navbar, Modal: Modal, Movies: Movies, Event: Event, SearchBar: SearchBar } } </script>



9. 원래 데이터 다시 보여주기
<template> <div> <Navbar /> <Event :text="text" /> <SearchBar :movies="movies_temp" @searchMovie="searchMovie($event)"/> <!--영화 데이터 넘겨주기--> <p> <button @click="showAllMovie">전체보기</button> </p> <Movies :movies="movies_temp" @openModal="isModal=true; selectedMovie=$even" @incrementLike="incrementLike($event)" /> <!-- 자식에게 변수 값 전달하기 --> <Modal :movies="movies" :isModal="isModal" :selectedMovie="selectedMovie" @closeModal="isModal=false" /> </div> </template> <script> import movies from './assets/movies'; import Navbar from './components/Navbar.vue'; import Modal from './components/Modal.vue'; import Movies from './components/Movies.vue'; import Event from './components/Event.vue'; import SearchBar from './components/SearchBar.vue'; export default { name: 'App', data() { return { isModal: false, selectedMovie: null, movies: movies, // 원본 데이터 movies_temp: [...movies], // 사본 데이터 text: "Neplix 강렬한 운명의 드라마, 경기크리처" } }, methods: { incrementLike(i) { this.movies[i].like++; }, selectMovie(i) { this.selectedMovie = i; this.isModal = true; }, searchMovie(title) { // 영화 제목이 포함된 데이터 this.movies_temp = this.movies.filter(movie => { return movie.title.includes(title); }) }, showAllMovie() { this.movies_temp = [...this.movies] } }, components: { Navbar: Navbar, Modal: Modal, Movies: Movies, Event: Event, SearchBar: SearchBar } } </script>


Share article