반응형
bootstrap에 spinner 클래스를 이용
https://getbootstrap.com/docs/5.1/components/spinners/
Spinners
Indicate the loading state of a component or page with Bootstrap spinners, built entirely with HTML, CSS, and no JavaScript.
getbootstrap.com
movie.js
import axios from 'axios'
// 중복제거을 위해서 uniqBy를 사용
import _uniqBy from 'lodash/uniqBy'
export default {
// module!
namespaced: true,
//data!
state: () => ({
movies: [],
message: 'Search for the movie title!',
loading: false
}),
// computed!
getters: {
// 실제 데이터를 계산해서 새로운 데이터 형식으로 반영할때 사용
},
// methods!
// 변이: 관리하는 데이터를 변경시켜줄수 있다. 다른 메소드에서 변경할 수 없다.
mutations: {
// ['movies', 'message', 'loading']
updateState(state, payload) {
Object.keys(payload).forEach(key => {
state[key] = payload[key]
})
},
// assignMovies (state, Search){
// state.movies = Search
// },
resetMovies(state) {
state.movies = []
}
},
// 비동기로 동작한다.
actions: {
async searchMovies({state, commit}, payload) {
// 영화검색을 동시에 동작하는 것을 방지
if(state.loading) {
return
}
commit('updateState', {
message: '',
loading: true
// 검색된 imdbID 데이터의 중복을 제거
// movies: _uniqBy(Search,'imdbID')
// message: 'Hello world',
// loading: true
})
try {
// const { title, type, number, year } = payload
// const OMDB_API_KEY = '7035c60c'
// http -> https 로 변경
//const res = await axios.get(`https://www.omdbapi.com/?apikey=${OMDB_API_KEY}&s=${title}&type=${type}&y=${year}&page=1`);
const res = await _fetchMovie({
// 전개연산자 사용
...payload,
page: 1
})
// console.log(res);
const { Search, totalResults } = res.data
commit('updateState', {
// 검색된 imdbID 데이터의 중복을 제거
movies: _uniqBy(Search,'imdbID')
// message: 'Hello world',
// loading: true
})
console.log(totalResults) // 261
console.log(typeof totalResults) // string
const total = parseInt(totalResults, 10)
const pageLength = Math.ceil(total / 10)
// 추가 요청!
if (pageLength > 1) {
for (let page = 2; page <= pageLength; page += 1) {
if (page > payload.number / 10) {
// 반복문 종료
// 사용자가 지정한 갯수만큼 보여주도록 설정
break;
}
//const res = await axios.get(`https://www.omdbapi.com/?apikey=${OMDB_API_KEY}&s=${title}&type=${type}&y=${year}&page=${page}`);
const res = await _fetchMovie({
...payload,
page: page
})
const {Search} = res.data
commit('updateState', {
// _uniqBy 를 이용해서 중복 제거
movies: [
...state.movies,
..._uniqBy(Search, 'imdbID')
]
})
}
}
} catch (message) {
commit('updateState', {
// 초기화
movies: [],
// 메세지 출력
message: message
})
} finally {
commit('updateState', {
loading: false
})
}
}
}
}
function _fetchMovie(payload) {
const { title, type, year, page } = payload;
const OMDB_API_KEY = '7035c60c';
const url = `https://www.omdbapi.com/?apikey=${OMDB_API_KEY}&s=${title}&type=${type}&y=${year}&page=${page}`;
// const url = `https://www.omdbapi.com/?apikey=${OMDB_API_KEY}`;
return new Promise((resolve, reject) => {
axios.get(url)
.then((res) => {
// console.log(res)
if (res.data.Error) {
reject(res.data.Error)
}
resolve(res)
})
.catch((err) => {
reject(err.message)
})
})
}
MovieList.vue
<template>
<div class="container">
<div
:class="{'no-result': !movies.length}"
class="inner">
<div
v-if="loading"
class="spinner-border text-primary"></div>
<div
v-if="message"
class="message">
{{ message }}
</div>
<div
v-else
class="movies">
<MovieItem
v-for="movie in movies"
:key="movie.imdbID"
:movie="movie" />
</div>
</div>
</div>
</template>
<script>
import MovieItem from '~/components/MovieItem.vue'
export default {
components: {
MovieItem
},
computed: {
movies(){
return this.$store.state.movie.movies
},
message(){
return this.$store.state.movie.message
},
loading() {
return this.$store.state.movie.loading
}
}
}
</script>
<style lang="scss" scoped>
@import "~/scss/main.scss";
.container {
margin-top: 30px;
.inner {
background-color: $gray-200;
padding: 10px 0;
border-radius: 4px;
text-align: center;
&.no-result {
padding: 70px 0;
}
}
.message {
color: $gray-400;
font-size: 20px;
}
.movies {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
}
</style>
로딩화면을 확인하기 위해서 일부러 인터넷속도를 느리게 설정이 가능하다
개발자 도구에서 네트워크 탭을 들어가서 느린속도로 설정한다.
반응형
'프론트엔드 > Vue.js' 카테고리의 다른 글
반복적인 내용을 효율적으로 관리하는 방법: Vuex Helpers (0) | 2022.01.13 |
---|---|
404 페이지 만들기 (0) | 2021.11.03 |
container 너비 사용자 지정 (0) | 2021.09.23 |
비동기 - API 비동기 처리 연습 (0) | 2021.09.13 |
비동기 예외 처리(then, catch, finally) (0) | 2021.09.10 |