HTML을 짜다보면 길거나 복잡한 코드를 많이 본다. <div>만 수십개가 나오는게 일상인데 이게 싫으면 컴포넌트를 만들어서 사용하면 된다.
만드는 법은 간단하다 아무이름.vue 파일을 아무데나 만드신 후 그 안에 축약할 HTML을 붙여넣어준다. 주의할 점은 반드시 .vue로 파일을 만들어 줘야한다.
// 아무이름.vue
<template>
//축약할 HTML
</template>
<script>
export default {
name: '아무이름',
}
</script>
<style>
</style>
이렇게 만들면 하나의 컴포넌트를 만든거다.
그 다음에 원하는 곳에 .vue파일을 import하고, 등록하고, 쓰면 된다.
<template> 안에다가 축약할 HTML을 넣고,
<style> 에다가 적용할 스타일을 넣어주면 된다.
마지막으로 <script> 안에 있는 name: '아무이름' 은 나중에 디버깅할 때 쓰는 이름이다.
컴포넌트를 쓰는 법은 아까 만들어둔 .vue파일을 import 하고, components 에다가 이름을 적어준 다음 <template> 안에 원하는 곳에다가 이름을 적어주면 된다.
<template>
<Modal>
</Modal>
</template>
import Modal from 'Modal.vue 경로'
export default {
data() {
},
components : {
Modal,
}
}
HTML 재사용이 쉬워진다.만약 Modal.vue 컴포넌트에 데이터바인딩을 해놨는데 그 안에 데이터바인딩한 데이터가 없고 부모 컴포넌트에 그 데이터가 있을 경우 props를 이용해서 부모 컴포넌트에 있던 데이터를 전송해서 쓰면 된다.
<Modal :oneRoomData = "oneRoomData"/>
...
data() {
return {
oneRoomData: oneRoomData,
};
},
<Modal: 아무이름="하단의데이터이름"/>
이렇게 하면 부모컴포넌트에 있는 oneRoomData를 <Modal>로 보낼 수 있다.
props로 등록한다.
...
export default {
name: 'Modal',
props: {
oneRoomData: Array,
},
}
이런식으로 props라는 오브젝트를 만들고 그 안에다 {데이터이름: 자료형}을 적어주면 된다.
자료형에는 Number, Array, Object, String 등 모든 자료형을 쓸 수 있다.
자식컴포넌트가 부모가 가진 데이터를 바꾸면 오류가 일어난다. 애초에 다른 파일에 있는거니까 오류가 걸리는게 당연하다. 또한, props로 전해준 데이터도 변경하면 안된다.
부모가 가진 데이터를 바꾸고 싶으면 custom event문법을 쓰면 된다. 방법을 요약 해보자면
$emit(아무이름, 전달할자료)를 쓰면 부모에게 메세지를 보낼 수 잇다. @아무이름="데이터변경하는JS코드" 이렇게 메세지를 수신해서 원하는 데이터를 변경할 수 있다. // Card.vue
<template>
<div>
<img :src="roomData.image" class="room_img" />
<button @click="$emit('openModal')">자세히 보기</button>
<hr />
<div>
</template>
...
// app.vue
<template>
<Card :roomData="roomData[i]" @openModal = 'modalOn = true'/>
</template>
...
부모에게 자료를 전달하는 법은 $event라는 변수를 쓰면 된다.
쫌전에 $emit()를 사용할 때 두번째 파라미터에다가 전달할자료를 적을 수 있다고 했었다. 여기에다가 원하는 자료를 부모에게 전달할 수 있다.
// Card.vue
<template>
<div>
<img :src="roomData.image" class="room_img" />
<h3>{{ roomData.title }}</h3>
<button @click="$emit('openModal', roomData.id)">자세히 보기</button>
<hr />
</div>
</template>
...
이런식으로 0번 상품은 roomData.id가 0, 1번 상품은 roomData.id가 1 이기 때문에 몇번째 모달을 눌렀는지 확인할 수 있다.
// App.vue
<template>
<Card :roomData="roomData[i]" v-for="(item, i) in roomData" :key="i" @openModal = 'modalOn = true; roomClick = $event'/>
</template>
...
그리고 부모는 $event라는 변수를 사용해서 roomClick이라는 값에는 0번 상품을 눌렀으면 0, 1번 상품을 눌렀으면 1이라는 값이 들어간다.
주의사항은 함수를 만들어서 사용해도 되는데 그럴때는 this.$emit()라고 해야한다.
<button @click="openModal">자세히 보기</button>
...
methods: {
openModal() {
this.$emit("openModal", this.roomData.id)
}