데일리 공부 기록

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. 버튼을 생성하여 로직을 만든다.