데일리 공부 기록
hands on vue - 부모->자식 데이터 넘기기 연습예
탐훈
2023. 3. 6. 12:34
728x90
[목표]
1. 부모-> 자식 데이터를 넘기고 해당 데이터를 변형하여 사용하는 데에 익숙함을 만들자
예제 :
자식 컴포넌트에 Favorite 버튼을 생성하고
클릭한 list가 Favorite 추가가 되도록 해라
수정 전 소스
[App.vue]
<template>
<section>
<ul>
<friend-contact
name="Manuel Lorenez"
phone-number="1234-5678-111"
email-address="gnsdl9079@gmail.com">
</friend-contact>
<friend-contact
name="Tom Hoon"
phone-number="010-2222-2222"
email-address="gnsdl9079@gmail.com">
</friend-contact>
</ul>
</section>
</template>
<script>
import FriendContact from './components/FriendContact.vue'
export default{
components: { FriendContact },
data(){
return{
friends:[
{
id: 'manuel',
name: 'Manuel Lorenz',
phone: '1234 5678 90',
email: 'manuel@localhost.com'
},
{
id: 'tom',
name: 'Tom Hoon',
phone: '9281 238 2910',
email: 'tomhoon@localhost.com'
},
],
}
},
methods: {
},
computed: {
}
}
</script>
<style>
/* @import url('https://fonts.googleapis.com/css2?family=Jost&display=swap'); */
* {
box-sizing: border-box;
}
html {
font-family: 'Jost', sans-serif;
}
body {
margin: 0;
}
header {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
margin: 3rem auto;
border-radius: 10px;
padding: 1rem;
background-color: #58004d;
color: white;
text-align: center;
width: 90%;
max-width: 40rem;
}
#app ul {
margin: 0;
padding: 0;
list-style: none;
}
#app li {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
margin: 1rem auto;
border-radius: 10px;
padding: 1rem;
text-align: center;
width: 90%;
max-width: 40rem;
}
#app h2 {
font-size: 2rem;
border-bottom: 4px solid #ccc;
color: #58004d;
margin: 0 0 1rem 0;
}
#app button {
font: inherit;
cursor: pointer;
border: 1px solid #ff0077;
background-color: #ff0077;
color: white;
padding: 0.05rem 1rem;
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.26);
}
#app button:hover,
#app button:active {
background-color: #ec3169;
border-color: #ec3169;
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.26);
}
</style>
[FriendContact.vue]
// FriendContace.vue 소스
<template>
<li>
<h2>{{name}}</h2>
<button @click="toggleDetails">{{detailVisible ? 'Hide' : 'Show'}}Details</button>
<ul v-if="detailVisible == true">
<li>
<strong>NAME: </strong>
{{name}}
</li>
<li>
<strong>PHONE: </strong>
{{phoneNumber}}
</li>
<li>
<strong>EMAIL: </strong>
{{emailAddress}}
</li>
</ul>
</li>
</template>
<script>
export default{
props: [
'name',
'phoneNumber',
'emailAddress',
],
data(){
return{
friend: {
id: 'manuel',
name: 'Manuel Lorenz',
phone: '1234 5678 90',
email: 'manuel@localhost.com'
},
detailVisible: false,
}
},
methods: {
toggleDetails() {
this.detailVisible = !this.detailVisible;
},
},
}
</script>
[main.js]
import { createApp } from 'vue';
import App from './App.vue';
import FriendContact from './components/FriendContact.vue';
const app = createApp(App);
app.component('friend-contact', FriendContact);
// app.component('사용할 태그명', 태그명 적용파일);
app.mount('#app');
수정 후 소스
[App.vue]
<template>
<section>
<ul>
<friend-contact
name="Manuel Lorenez"
phone-number="1234-5678-111"
email-address="gnsdl9079@gmail.com"
is-favorite="1"
>
<!-- 1일때 true, 0일때 false -->
</friend-contact>
<friend-contact
name="Tom Hoon"
phone-number="010-2222-2222"
email-address="gnsdl9079@gmail.com"
is-favorite="0"
>
</friend-contact>
</ul>
</section>
</template>
<script>
import FriendContact from './components/FriendContact.vue'
export default{
components: { FriendContact },
data(){
return{
friends:[
{
id: 'manuel',
name: 'Manuel Lorenz',
phone: '1234 5678 90',
email: 'manuel@localhost.com'
},
{
id: 'tom',
name: 'Tom Hoon',
phone: '9281 238 2910',
email: 'tomhoon@localhost.com'
},
],
}
},
methods: {
},
computed: {
}
}
</script>
<style>
/* @import url('https://fonts.googleapis.com/css2?family=Jost&display=swap'); */
* {
box-sizing: border-box;
}
html {
font-family: 'Jost', sans-serif;
}
body {
margin: 0;
}
header {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
margin: 3rem auto;
border-radius: 10px;
padding: 1rem;
background-color: #58004d;
color: white;
text-align: center;
width: 90%;
max-width: 40rem;
}
#app ul {
margin: 0;
padding: 0;
list-style: none;
}
#app li {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
margin: 1rem auto;
border-radius: 10px;
padding: 1rem;
text-align: center;
width: 90%;
max-width: 40rem;
}
#app h2 {
font-size: 2rem;
border-bottom: 4px solid #ccc;
color: #58004d;
margin: 0 0 1rem 0;
}
#app button {
font: inherit;
cursor: pointer;
border: 1px solid #ff0077;
background-color: #ff0077;
color: white;
padding: 0.05rem 1rem;
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.26);
}
#app button:hover,
#app button:active {
background-color: #ec3169;
border-color: #ec3169;
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.26);
}
</style>
[FriendContact.vue]
// FriendContace.vue 소스
<template>
<li>
<button @click="toggleFavorite">Favorite Change</button>
<h2>{{name}} {{isFavorite_child? 'Favorite' : ''}}</h2>
<button @click="toggleDetails">{{detailVisible ? 'Hide' : 'Show'}}Details</button>
<ul v-if="detailVisible == true">
<li>
<strong>NAME: </strong>
{{name}}
</li>
<li>
<strong>PHONE: </strong>
{{phoneNumber}}
</li>
<li>
<strong>EMAIL: </strong>
{{emailAddress}}
</li>
</ul>
</li>
</template>
<script>
export default{
props: [
'name',
'phoneNumber',
'emailAddress',
'isFavorite'
],
data(){
return{
friend: {
id: 'manuel',
name: 'Manuel Lorenz',
phone: '1234 5678 90',
email: 'manuel@localhost.com'
},
detailVisible: false,
isFavorite_child: false,
}
},
methods: {
toggleDetails() {
this.detailVisible = !this.detailVisible;
},
toggleFavorite(){
this.isFavorite_child = !this.isFavorite_child;
}
},
}
</script>
main.js는 수정이 없어서 안올림.
수정 순서
1. App.vue(부모)에서 케밥케이스로 넘긴다.(is-favorite)
2. FriendContact.vue(자식)의 props에서 받는다.(isFavorite)
3. props에서 받은 데이터를 자식 데이터 고유의 변수에 담는다
=> 왜냐하면 부모 컴포넌트가 보낸 데이터를 자식데이터에서 감히 수정할 수 없다.
this.isFavorite_child = this.isFavorite;
4. 버튼을 생성하여 로직을 만든다.