이안의 평일코딩

[Vue] Vue의 기초(5) - Component, props, custom event 본문

Front-end/Vue

[Vue] Vue의 기초(5) - Component, props, custom event

이안92 2021. 4. 12. 15:13
반응형

 Component

 

컴포넌트 문법은 재사용이 간단하고 반복적으로 출현할 부분 컴포넌트화 권장된다.

다른 곳에서 쓸 것 같거나 라우터로 나눌 페이지 혹은 HTML이 너무 길어서 복잡할 때 사용한다.

Vue파일을 만들고 <template>에 축약할 HTML을 넣은 뒤 <script>에 name을 넣는다.

 

Discount.vue
<template>
    <div class="discount">
        <h4>지금 결제하면 20% 할인</h4>
    </div>
</template>
<script>
export default {
    name: 'Discount',
}
</script>
<style>
.discount {
    background: #eee;
    padding: 10px;
    margin: 10px;
    border-radius: 5px;
}
</style>

먼저 vue파일을 <script>에서 import해오고 components에 등록 후 <template>에 축약해둔 컴포넌트를 <Discount />처럼 넣어준다.

 

App.vue
<template>
  <div class="menu">
    <a v-for="a in menus" :key="a">{{a}}</a>
  </div>
  
  <Discount />
</template>

<script>
import Discount from './Discount';

export default {
  name: 'App',
  data(){
    return {
      menus : ['Home', 'Shop', 'About'],
    }
  },
  components: {
    Discount,
  }
}
</script>

 

 

 props

 

부모가 가진 데이터를 자식이 쓰고 싶을 때 사용한다.

데이터는 보통 한 곳에 보관하고 props를 통해 필요할 때 가져다 쓴다.

 

먼저 부모에서 <자식 :데이터="데이터">로 데이터를 보내고

자식은 props:{데이터이름:자료형이름}으로 등록하고(자료형 Object, Array, String, Number,...) 사용하면 된다.

props는 read-only이기 때문에 받아온 것을 수정하면 오류가 난다.

하위 자식컴포넌트에만 필요하면 자식에 데이터를 만들면 되긴하지만 부모도 쓰는 데이터라면 부모 컴포넌트에 만든다.

 

App.vue
<template>
  <Modal :oneroom="oneroom" :clicked="clicked" :modal="modal" />
</template>

<script>
import data from './assets/oneroom';
import Modal from './Modal';

export default {
  name: 'App',
  data(){
    return {
      oneroom : data,
      clicked : 0,
      modal : false,
    }
  },
  components: {
    Modal,
  }
}
</script>

 

Modal.vue
<template>
  <div class="black-bg" v-if="modal == true">
    <div class="white-bg">
      <h4>{{oneroom[clicked].title}}</h4>
      <p>{{oneroom[clicked].content}}</p>
      <!-- <button @click="modal = false">닫기</button> -->
    </div>
  </div>
</template>

<script>
export default {
    name : 'Modal',
    props : {
        oneroom : Array,
        clicked : Number,
        modal : Boolean,
    }
}
</script>

 

 

 props 여러번 써야할 때는?

 

예를들어, App.vue에서 Container로 props하고 Container안에 들어있는 Post.vue로 props를 보내줘야할 때에는 Container.vue에서 받아서 다시 Post.vue로 보내어 받으면 된다.

 

App.vue
<template>
  <Container :userData="userData" />
</template>

<script>
import Container from './components/Container.vue';
import data from './assets/data';

export default {
  name: 'App',
  data(){
    return {
      userData : data,
    }
  },
  components: {
    Container,
  },
}
</script>
Container.vue
<template>
  <div>
      <Post v-for="(a,i) in userData" :key="i" :userData="userData[i]" />
  </div>
</template>

<script>
import Post from './Post';
export default {
    props : {
        instaData : Array,
    },
    components: {
        Post,
    }
}
</script>
Post.vue
<template>
  <div class="post">
      <span class="name">{{userData.name}}</span>
  </div> 
</template>

<script>
export default {
    props : {
        userData : Array,
    },
}
</script>

 

 

 custom event

 

자식이 부모데이터를 바꾸고 싶을 때 사용한다. 자식컴포넌트에서 부모에게 메세지 보낼 땐 $emit('작명', 데이터), 부모가 메세지 수신할 때 @작명한거="데이터변경하는JS코드". 자식이 보낸 데이터는 $event 변수에 담겨있다.

 

Card.vue
<template>
  <div>
    <img :src="oneroom.image" class="room-img">
    <h4 @click="$emit('openModal', oneroom.id)">{{oneroom.title}}</h4>
    <p>{{oneroom.price}}원</p>
  </div>
</template>

<script>
export default {
    name: 'Card',
    props: {
        oneroom : Object,
    }
}
</script>

<style>
.room-img {
  width: 100%;
  margin-top: 40px;
}
</style>

 

App.vue
<template>
  <Card @openModal="modal=true; clicked=$event"
        :oneroom="oneroom[i]" v-for="(a,i) in oneroom" :key="i"/>
</template>

<script>
import data from './assets/oneroom';
import Card from './Card';

export default {
  name: 'App',
  data(){
    return {
      oneroom : data,
      clicked : 0,
      modal : false,
    }
  },
  components: {
    Card,
  }
}
</script>
반응형
Comments