Vue는 사용자 인터페이스를 만들기 위한 프로그레시브 프레임워크 이다.
// 컴포넌트
const App = {
// data 옵션은 함수여야한다.
// 콜론 function 생략
data() {
return {
// title이라는 데이터를 정의한 것
title: '',
};
},
methods: {
// methods에는 this키워드 써야해서 일반함수로 사용해야함, 화살표함수 (x)
},
};
Vue.createApp(App).mount('#app');
:
<input v-bind:value="title" />
v-bind를 입력하면 이제 title은 글자가 아니라 데이터가된다. (위에서 정의한 Vue.js쪽 데이터 이름이 되는 것)
Vue.js로 정의한 데이터는 반응형 데이터라고 부르거나 반응성을 가진 데이터라고 부른다.
@
<button v-on:click="changeTitle">Click!</button>
// 컴포넌트
const App = {
data() {
return {
// 타이틀이라는 데이터
title: '',
};
},
methods: {
changeTitle() {
this.title = 'YEJIN!'
}
},
};
Vue.createApp(App).mount('#app');
this
키워드 작성한다.const App = {
data() {
return {
title: '',
// 데이터를 받아 줄 반응형데이터(movies)를 지정
movies: [],
};
},
methods: {
async searchMovies() {
let res = await fetch(
`https://www.omdbapi.com/?apikey=${API_KEY}=${this.title}&page=1`
);
res = await res.json();
console.log(res);
// 1. 받은 데이터를 꺼낸다.
const { Search, totalResults } = res
// 2. 할당해준다. movies는 빈 배열이였지만 Search라는 10개 데이터를 가진 배열이 됨
this.movies = Search
},
},
};
Vue.createApp(App).mount('#app');
화면에 출력하기 위한 코드
<div id="app">
<input v-model="title" />
<button v-on:click="searchMovies">Search!</button>
<ul>
<li v-for="movie in movies">{{ movie.Title }}</li>
</ul>
v-model
이다.v-for
를 이용해서 배열데이터 movies를 화면에 출력한다.in
키워드 앞에는 내가 원하는 변수명을 쓸 수 있다. {{ }}
로 출력 <ul>
<li v-for="movie in movies" :key="movie.id">
<img :src="movie.poster" alt="" height="40" />
{{ movie.Title }}
</li>
</ul>
v-bind
를 써줘야 반응형 데이터가 된다.:
사용<button v-on:click="searchMoviesMore">More..</button>
const App = {
data() {
return {
title: '',
page: 1,
movies: [],
};
},
methods: {
// 최초 요청 최초의 10개
async searchMovies() {
// 최초라서 페이지를 1로 초기화해주고
this.page = 1;
let res = await fetch(
`https://www.omdbapi.com/?apikey=${API_KEY}&s=${this.title}&page=${this.page}`
);
res = await res.json();
console.log(res);
const { Search, totalResults } = res;
this.movies = Search;
// 1에서 2로 올라간 다음 아래 코드가 실행
this.page = 2;
},
// 페이지를 더 가져오는 함수
async searchMoviesMore() {
let res = await fetch(
`https://www.omdbapi.com/?apikey=${API_KEY}&s=${this.title}&page=${this.page}`
);
res = await res.json();
console.log(res);
const { Search, totalResults } = res;
// 최초배열의 뒤에 새로운 데이터를 push로 밀어넣어준다.
// Search는 배열데이터, 전개 연산자 사용해서 내용물만 사용
this.movies.push(...Search);
// 페이지가 1씩 증가, 결국 3이 됨
// 3에서 버튼을 누르면 다시 1로 초기화 하는 로직
this.page += 1;
},
},
};
Vue.createApp(App).mount('#app');
More 버튼은 최초 검색이 일어난 이후에 나오게 해야한다.
Movies 배열이 비어져 있으면 More 버튼이 보일 필요가 없다.
배열에 item이 몇개 있는지 length 메소드를 활용한다.
<button v-if="movies.length > 0"v-on:click="searchMoviesMore">More..</button>
<!-- > 0 는 굳이 안 적어도 된다. 1이상은 전부다 truthy. 값이 없으면 어차피 0 -->
즉, length가 0보다 클 때만 렌더링 해주세요!
v-if
는 디렉티브의 표현식이 true 값을 반환할 때만 렌더링된다.
<input v-model="title" v-on:keydown.enter="searchMovies(true)" />
v-on:keydown.enter
사용
const App = {
data() {
return {
title: '',
page: 1,
movies: [],
};
},
methods: {
// 최초 요청 최초의 10개
async searchMovies() {
// 최초라서 페이지를 1로 초기화해주고
this.page = 1;
let res = await fetch(
`https://www.omdbapi.com/?apikey=${API_KEY}&s=${this.title}&page=${this.page}`
);
res = await res.json();
console.log(res);
const { Search, totalResults } = res;
this.movies = Search;
// 1에서 2로 올라간 다음 아래 코드가 실행
this.page = 2;
},
// 페이지를 더 가져오는 함수
async searchMoviesMore() {
let res = await fetch(
`https://www.omdbapi.com/?apikey=${API_KEY}&s=${this.title}&page=${this.page}`
);
res = await res.json();
console.log(res);
const { Search, totalResults } = res;
// 최초배열의 뒤에 새로운 데이터를 push로 밀어넣어준다.
// Search는 배열데이터, 전개 연산자 사용해서 내용물만 사용
this.movies.push(...Search);
// 페이지가 1씩 증가, 결국 3이 됨
// 3에서 버튼을 누르면 다시 1로 초기화 하는 로직
this.page += 1;
},
},
};
Vue.createApp(App).mount('#app');
현재 searchMovies()
searchMoviesMore()
해당 함수들에 로직이 같은 부분이 있다. 단일 함수로 사용하는것이 중요하다.
목표: searchMovies
함수에 합치기
<div id="app">
<input v-model="title" />
<button v-on:click="searchMovies(true)">Search!</button>
<ul>
<li v-for="movie in movies">
<img v-bind:src="movie.Poster" alt="" height="40" />
{{ movie.Title }}
</li>
</ul>
<button v-if="movies.length" v-on:click="searchMovies()">More..</button>
</div>
v-on:click
에 메소드 연결하면서 실행()
을 따로 걸 수 있다. true
넣어 주고 More 버튼을 클릭은 아무것도 넣지 않는다.const App = {
data() {
return {
title: '',
page: 1,
movies: [],
};
},
methods: {
// 최초 요청 최초의 10개
// isFirst라는 매개변수를 지정 → 최초 검색인지 아닌지를 판단
// isFirst에는 truthy가 들어와야 최초 검색이됨
async searchMovies(isFirst) {
if (isFirst) {
// 최초 검색일 때 빈배열로 초기화하라
// 최초 검색일 때 페이지를 1로 초기화하라
this.movies = [];
this.page = 1;
}
let res = await fetch(
`https://www.omdbapi.com/?=apikey=${API_KEY}&s=${this.title}&page=${this.page}`
);
res = await res.json();
console.log(res);
const { Search, totalResults } = res;
this.movies.push(...Search);
this.page += 1;
},
},
};
Vue.createApp(App).mount('#app');
오늘은 문법보다 뷰가 어떻게 동작하는지 흐름을 알기 위해 영화 검색 API를 활용해서 화면에 출력하는 것을 해봤다. 현재 영화 검색 과제를 바닐라 자바스크립트로 구현하고 있는데, 같은 것을 뷰로 구현해보니 왜 프레임워크를 쓰는지 확실히 알았고 코드가 간편해졌다! 정말 좋은 친구였어.. 쀼야 친해지자..🥹