본문 바로가기

데일리 공부 기록

hands on vue - emit 연습문제 (@submit.prevent, emit, vue.component )

728x90

[목표]

1. 부모 - 객체 간의 데이터 전달에 필요한 기능들을 익숙해져 보자

 

1-1) @submit.prevent란 무엇인가

1-2) App.vue(부모)에서 컴포넌트 형식으로 사용하려면 어떻게?

1-3) emit를 하기위한 순서는?

 


1-1) @submit.prevent란 무엇인가

form 태그 사용시 페이지가 넘어가는 동작을 한다. 

이것을 막아주는 기능이다.

 

1-2) App.vue(부모)에서 컴포넌트 형식으로 사용하려면 어떻게?

 

1st: main.js에서 등록한다

import { createApp } from 'vue';
import App from './App.vue';
import FriendContact from './components/FriendContact.vue';
import NewFriend from './components/NewFriend.vue';

const app = createApp(App);
app.component('friend-contact', FriendContact);
// app.component('사용할 태그명', 태그명 적용파일);
app.component('new-friend', NewFriend);
app.mount('#app');

2nd: App.vue 안에 전언한 태그명으로 사용한다.

[App.vue]

<template>
<section>
    <ul>
      <new-friend
        @new-freind="emitNewFriend"
        >

      </new-friend>
      <FriendContact
        v-for="friend in friends"
        :key="friend.id"
        :id="friend.id"
        :name="friend.name"
        :phone-number="friend.phoneNumber"
        :email-address="friend.emailAddress"
        :isFavorite="friend.isFavorite"
        @toggle-favorite="emitToggle"
      >
      </FriendContact>S
    </ul>
</section>
</template>

<script>
import FriendContact from './components/FriendContact.vue'
import NewFriend from './components/NewFriend.vue'

export default{ 
  components: { 
    FriendContact,
    NewFriend,

  },
        data(){
            return{
                friends:[
                    {
                       id: 'manuel',
                       name: 'Manuel Lorenz',
                       phone: '1234 5678 90', 
                       email: 'manuel@localhost.com',
                       isFavorite: true,
                    },
                    {
                       id: 'tom',
                       name: 'Tom Hoon',
                       phone: '9281 238 2910', 
                       email: 'tomhoon@localhost.com',
                       isFavorite: false,
                    },
                    {
                       id: 'Ann',
                       name: 'Ann Kim',
                       phone: '9523 591 2330', 
                       email: 'ann@localhost.com',
                       isFavorite: false,
                    },
                ],
            }
        },
        methods: {
          emitToggle(value){
            const result = this.friends.find(function(x){
              return x.id == value;
            });
            result.isFavorite = !result.isFavorite;
          },
          emitNewFriend(){
            alert('emitNewFriend');
          },
        },
        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 form {
  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>


1-3) emit를 하기위한 순서는?

 

1st: 부모객체로 보낼 자식객체에서 emit 변수명 선언

2nd: form에서 다양한 설정을 한다. 설정은 다음과 같다.

2-1) v-model 

2-2) @submit.prevent="submit 시에 작동할 메소드명"

 

3rd: App.vue(부모)에서 자식이 보낸 emit를 등록한다.

4th: 자식이 emit를 보내면 부모가 반응하여 작동할 method 생성

여기까지 설명이였고 밑에 연습문제와 해답을 올리겠음


[연습문제]

[App.vue]

<template>
<section>
    <ul>
      <FriendContact
        v-for="friend in friends"
        :key="friend.id"
        :id="friend.id"
        :name="friend.name"
        :phone-number="friend.phoneNumber"
        :email-address="friend.emailAddress"
        :isFavorite="friend.isFavorite"
        @toggle-favorite="emitToggle"
      >
      </FriendContact>S
    </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',
                       isFavorite: true,
                    },
                    {
                       id: 'tom',
                       name: 'Tom Hoon',
                       phone: '9281 238 2910', 
                       email: 'tomhoon@localhost.com',
                       isFavorite: false,
                    },
                    {
                       id: 'Ann',
                       name: 'Ann Kim',
                       phone: '9523 591 2330', 
                       email: 'ann@localhost.com',
                       isFavorite: false,
                    },
                ],
            }
        },
        methods: {
          emitToggle(value){
            const result = this.friends.find(function(x){
              return x.id == value;
            });
            result.isFavorite = !result.isFavorite;
          },
        },
        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 form {
  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>

[NewFriend.vue]

<template>
    <form>
        <div>
            <label for="name">name: </label>
            <input type="text" v-model="newFriend.name">
        </div>
        <div>
            <label for="phone">phone: </label>
            <input type="text" v-model="newFriend.phone">
        </div>
        <div>
            <label for="email">email: </label>
            <input type="text" v-model="newFriend.email">
        </div>
        <button>Submit</button>
    </form>
</template>

<script>
    export default{

        data: function(){
            return{

            }
        },
        methods: {

        },

    }
</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>
      <new-friend
        @add-friend="addFriend"
        >

      </new-friend>

      <FriendContact
        v-for="friend in friends"
        :key="friend.id"
        :id="friend.id"
        :name="friend.name"
        :phone-number="friend.phoneNumber"
        :email-address="friend.emailAddress"
        :isFavorite="friend.isFavorite"
        @toggle-favorite="emitToggle"
      >
      </FriendContact>S
    </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',
                       isFavorite: true,
                    },
                    {
                       id: 'tom',
                       name: 'Tom Hoon',
                       phone: '9281 238 2910', 
                       email: 'tomhoon@localhost.com',
                       isFavorite: false,
                    },
                    {
                       id: 'Ann',
                       name: 'Ann Kim',
                       phone: '9523 591 2330', 
                       email: 'ann@localhost.com',
                       isFavorite: false,
                    },
                ],
            }
        },
        methods: {
          emitToggle(value){
            const result = this.friends.find(function(x){
              return x.id == value;
            });
            result.isFavorite = !result.isFavorite;
          },
          addFriend(value){
            const newFriend = {
              id:new Date().toISOString(),
              name:value.name,
              phone:value.phone,
              email:value.email,
            };
            this.friends.push(newFriend);
          }
        },
        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 form {
  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>

[NewFriend.vue]

더보기
<template>
    <form @submit.prevent="addFriend">
        <div>
            <label for="name">name: </label>
            <input type="text" v-model="newFriend.name">
        </div>
        <div>
            <label for="phone">phone: </label>
            <input type="text" v-model="newFriend.phone">
        </div>
        <div>
            <label for="email">email: </label>
            <input type="text" v-model="newFriend.email">
        </div>
        <button>Submit</button>
    </form>
</template>

<script>
    export default{
        emit:['add-friend'],
        data: function(){
            return{
                newFriend:{
                    name: '',
                    phone: '',
                    email: '',
                }
            }
        },
        methods: {
            addFriend(){
                this.$emit('add-friend', this.newFriend);
            }
        },

    }
</script>

[main.js]

더보기
import { createApp } from 'vue';
import App from './App.vue';
import FriendContact from './components/FriendContact.vue';
import NewFriend from './components/NewFriend.vue';

const app = createApp(App);

// app.component('사용할 태그명', 태그명 적용파일);
app.component('friend-contact', FriendContact);
app.component('new-friend', NewFriend);

app.mount('#app');

결과물