Recent Posts
Recent Comments
์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- ์๊ณ ๋ฆฌ์ฆ
- ํ๋ก ํธ์๋
- position
- ๋ธ๋ก๊ทธ
- ์ฝ๋ฉํ ์คํธ
- ํ๋ก๊ทธ๋๋จธ์ค
- Props
- float
- ๋ฐ๋ธ์ฝ์ค3๊ธฐ
- useRef
- fetch API
- ๋ฐ๋ธ์ฝ์ค
- REACT
- ์๋ฐ์คํฌ๋ฆฝํธ
- useEffect
- Gatsby
- CSS
- history api
- Flex
Archives
- Today
- Total
Daehyunii's Dev-blog
8์ฃผ์ฐจ ๊ณผ์ - Vue ์ํ ๊ฒ์ ํ์ด์ง ๋ง๋ค๊ธฐ ๋ณธ๋ฌธ
๐ Dev Course/Assignment
8์ฃผ์ฐจ ๊ณผ์ - Vue ์ํ ๊ฒ์ ํ์ด์ง ๋ง๋ค๊ธฐ
Daehyunii 2022. 12. 13. 23:59
App.vue
<template>
<div class="page-all">
<div class="pageSubject">
<h1>
{{ header }}
</h1>
</div>
<search-bar />
</div>
</template>
<script>
import SearchBar from "~/components/SearchBar";
export default {
components: {
SearchBar,
},
data() {
return {
header: "๐ฌ ์ํ ๊ฒ์",
};
},
};
</script>
<style lang="scss">
.page-all {
background-color: black;
height: 100%;
.pageSubject {
color: white;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
font-size: 50px;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
margin-bottom: 30px;
padding-top: 50px;
}
}
</style>
SearchBar.vue
<template>
<div class="search-bar">
<input
class="search-bar-input"
:value="keyword"
placeholder="์ํ ์ ๋ชฉ์ ์
๋ ฅํด ์ฃผ์ธ์."
@input="keyword = $event.target.value"
@keyup.enter="onSearch"
/>
<button class="search-bar-btn" @click="onSearch">๐</button>
</div>
<div v-if="hasResult" class="movie-lists">
<div
v-for="title of titles"
:key="title.imdbID"
class="movie-list"
@click="
getDetailData(title.imdbID);
changeModalState();
"
>
<img :src="title.Poster" alt="ํด๋น ์ํ๋ ํฌ์คํฐ๊ฐ ์์ต๋๋ค." />
<div class="movie-container">
<div class="movie-title">
{{ title.Title }}
</div>
<div class="movie-basic-info">
Year : {{ title.Year }} / Type : {{ title.Type }}
</div>
</div>
</div>
<button
v-if="totalResults > 10 && Math.ceil(totalResults / 10) > pageCount"
class="more-btn"
@click="pageCountUp"
>
โ ๋ ๋ณด๊ธฐ
</button>
</div>
<div v-else class="basic-background-color"></div>
<movie-info
:result="result"
:modalstate="modalstate"
@resetmodal="resetmodal"
/>
</template>
<script>
import MovieInfo from "~/components/MovieInfo";
export default {
components: {
MovieInfo,
},
data() {
return {
keyword: "",
titles: [],
totalResults: 0,
pageCount: 1,
result: {},
hasResult: false,
modalstate: false,
};
},
methods: {
async getData() {
const temp = this.titles;
const res = await fetch(
`API๋ ๊ณต๊ฐํ์ง ์๊ฒ ์ต๋๋ค~`
).then((res) => res.json());
const { Response, Search, totalResults } = res;
if (Response === "True") {
this.titles = [...temp, ...Search];
this.totalResults = totalResults;
this.hasResult = true;
} else {
this.titles = [];
this.totalResults = 0;
this.hasResult = false;
alert("๊ฒ์ ๊ฒฐ๊ณผ๊ฐ ์์ต๋๋ค.");
}
},
//๋ ๋ณด๊ธฐ ๋ฒํผ!
pageCountUp() {
this.pageCount = this.pageCount + 1;
this.getData();
},
onSearch() {
this.titles = [];
this.totalResults = 0;
this.pageCount = 1;
this.getData();
},
async getDetailData(id) {
const res = await fetch(
`API๋ ๊ณต๊ฐํ์ง ์๊ฒ ์ต๋๋ค~`
).then((res) => res.json());
this.result = res;
},
changeModalState() {
this.modalstate = true;
},
resetmodal(value) {
this.modalstate = value;
},
},
};
</script>
<style scoped lang="scss">
.search-bar {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 30px;
.search-bar-input {
width: 400px;
font-size: 30px;
box-shadow: 2px 2px 2px #dcdcdc;
margin-right: 15px;
margin-bottom: 20px;
border-radius: 20px;
padding-left: 20px;
padding-right: 20px;
}
.search-bar-btn {
font-size: 30px;
margin-bottom: 20px;
}
::placeholder {
font-size: 23px;
color: #d2d2d2;
}
}
.movie-lists {
display: grid;
grid-template-rows: 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
justify-content: space-around;
flex-wrap: wrap;
.movie-list {
border-radius: 15px;
background-color: white;
box-shadow: 4px 4px 4px #dcdcdc;
font-size: 25px;
text-align: center;
padding: 50px;
margin: 30px;
width: 400px;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}
.movie-title {
margin-top: 30px;
}
.movie-basic-info {
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
font-size: 17px;
padding-top: 15px;
color: gray;
}
.more-btn {
box-shadow: 4px 4px 4px #dcdcdc;
font-size: 30px;
text-align: center;
padding: 50px;
margin: 30px;
width: 500px;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
border-radius: 15px;
background-color: white;
}
}
.basic-background-color {
background-color: black;
color: #969696;
height: 1200px;
font-size: 25px;
margin-left: 60px;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}
</style>
MovieInfo.vue
<template>
<div v-if="$props.modalstate" class="modal" @click="onEmit">
<div class="modal-content">
<h1 class="movie-title">์ ๋ชฉ : {{ result.Title }}</h1>
<div class="movie-poster">
<img :src="result.Poster" alt="ํด๋น ์ํ์ ํฌ์คํฐ๊ฐ ์์ต๋๋ค." />
</div>
<div class="detail-movie-info">
<div>๐ ๊ฐ๋ด์ผ : {{ result.Released }}</div>
<div>โณ ์์์๊ฐ : {{ result.Runtime }}</div>
<div>๐ฝ ์ฅ๋ฅด : {{ result.Genre }}</div>
<div>๐ฌ ๊ฐ๋
: {{ result.Director }}</div>
<div>๐ฅ ๋ฐฐ์ฐ : {{ result.Actors }}</div>
<div>๐ ์์ ๊ฒฝ๋ ฅ : {{ result.Awards }}</div>
<div>๐ ์ค๊ฑฐ๋ฆฌ : {{ result.Plot }}</div>
<ul class="detail-movie-score">
โ๏ธ ํ์
<li v-for="score of result.Ratings">
−{{ score.Source }}, {{ score.Value }}
</li>
</ul>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
result: Object,
modalstate: Boolean,
},
data() {
return {
modalState: false,
};
},
methods: {
onEmit() {
this.$emit("resetmodal", false);
},
},
};
</script>
<style lang="scss">
.modal {
z-index: 1;
width: 100%;
height: 100%;
position: fixed;
left: 0;
top: 0;
background-color: rgba(0, 0, 0, 0.3);
.modal-content {
border-radius: 15px;
background-color: white;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 800px;
height: 800px;
overflow-y: auto;
overscroll-behavior: contain;
}
.movie-title {
margin: 40px 0px;
display: flex;
align-content: center;
justify-content: center;
font-size: 30px;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}
.movie-poster {
display: flex;
align-content: center;
justify-content: center;
margin-bottom: 30px;
}
}
.detail-movie-info {
padding: 30px;
display: flex;
flex-direction: column;
gap: 20px;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}
</style>