컴포넌트.vue이름을 2단어 이상으로 작명하지 않으면 에러가 남
(DiscountBanner.vue2단어 식으로 이름지어야 한다!)
👀싫으면package.json파일 ->rules에"vue/multi-word-component-names": "off"코드 추가할것
(미리보기 껐다가 다시 띄우면 됨)"rules": { "vue/multi-word-component-names": "off" }
HTMl이 너무 길때 2 단어로 축약할 수 있는 문법.
🤫복잡해 보이는데 굳이 왜 쓸까?
✔️ 코드 정리가 편하다.
✔️ HTMl 재사용이 쉬워진다.
✔️ 라우터로 페이지 구분하고 싶으면 하나의 페이지는 하나의 컴포넌트로 만드는게 좋다.
vue 파일을 만든 후 축약할 HTML을 넣는다.
❗️형식대로 만들어야 한다.
<template>
// 축약할 HTML
</template>
<script>
export default {
name : '작명', // 디버깅할때 쓰는 이름
data() {
return { // 넣을 data }
},
}
</script>
<style>
// 넣을 style
</style>
component 파일을 App.vue파일에서 import 해서 불러온다.<script> - components에 저장해 사용한다.// [ ModalRoom.vue (컴포넌트 파일) ]
<template>
<div class="black-bg" v-if="모달창 == true">
<div class="white-bg">
<h4>{{원룸들[누른거].title}}</h4>
<p>{{원룸들[누른거].content}}</p>
<img :src= "원룸들[누른거].image" class="roomImg">
<p>{{ 원룸들[누른거].price }}만원</p>
<button v-on:click="모달창=false">닫기</button>
</div>
</div>
</template>
<script>
export default {
name:'ModalRoom'
}
</script>
<style>
</style>
// [ App.vue ]
<template>
<Modol/> // 3. 사용하기
</template>
<script>
import Modol from './Modal.vue'; // 1. 불러오기
export default {
name: "App",
data() {},
methods: {},
components: {
Modol : Modol // 2. 저장하기
},
};
</script>
해서 사용하면 된다!
🤫 근데 잘 될거같은데 되지 않는다...
✔️ 데이터바인딩할 때 문제가 생겨서!
<h4>{{원룸들[누른거].title}}</h4>
<p>{{원룸들[누른거].content}}</p>
<img :src= "원룸들[누른거].image" class="roomImg">
<p>{{ 원룸들[누른거].price }}만원</p>
{{원룸들}} 을 데이터바인딩 했는데 Model.vue 파일에는 해당하는 데이터가 없기 때문이다.
(데이터바인딩하려면 데이터가 밑에 있어야 한다.)
🤫 그럼 데이터를 넣어주면 될까?
✔️ 만약 데이터를 수정해야하면 복사본들 다 찾아서 이케저케...... 안된다!!
👉 부모가 가진 데이터를 props로 전달해서 써야한다!
하위 컴포넌트로 데이터를 전송하는 문법
👀부모 컴포넌트 / 자식 컴포넌트란
App.vue안에 Abc.vue를 집어 넣어 쓰고 있다고 가정할때
App.vue = 상위|부모 컴포넌트 / Abc.vue = 하위/자식 컴포넌트 라고 비유해 부른다.
App.vue에 있는 데이터를 Abc.vue / Def.vue 에 보낸다고 가정해보자
부모 컴포넌트에서 데이터바인딩 문법(:)을 쓰면 데이터를 보낼 수 있다.
<자식컴포넌트 v-bind:작명="데이터명">/<자식컴포넌트 :작명="데이터명">
:은 데이터바인딩 또는 props 전송이다.
Props 보내는 여러가지 방법
Obj = {name : 'kim', age : 20}
<A :데이터이름="[1,2,3]" /> // 배열을 한번에 보내기
<A :데이터이름="{ name:kim, age:20 }" /> // 오브젝트를 보내기
<A :데이터이름="obj.name" :데이터이름="obj.age"/> // 오브젝트를 하나씩 보내기
<A :데이터이름="obj"/> // 오브젝트를 한번에 보내기 <-(:데이터이름=:"오브젝트명")
<A :데이터이름="100" /> // 숫자 보내기
<A 데이터이름="안녕" /> // :을 붙이지 않으면 문자 보내기
//[ App.vue(부모컴포넌트) ]
<template>
<div>
<Abc v-bind:원룸="원룸들" :num="num"/>
// Abc 컴포넌트에 "원룸들"이라는 데이터를 "원룸"이라는 이름으로 전달!
// 작명은 데이터명과 달라도, 같아도 상관없다
</div>
</template>
자식 컴포넌트는 데이터를 받으면
<script>-props로 등록한다.
props:{데이터이름:자료형}
자료형은 Arraym, Object, String, Number, Boolean 등
//[ Abc.vue(자식컴포넌트) ]
<script>
export default {
name : 'Abc',
props : {
원룸 : Array,
num: Number,
}
}
</script>
props 등록한 것들은 HTML안에서 데이터바인딩으로 자유롭게 사용가능하다.
단, props는 그냥 받아서 사용만 하는 read-only 데이터처럼 취급하셔야지 수정하면 에러난다.
🤫 그냥 자식컴포넌트에 쓰는 데이터는 자식컴포넌트 데이터보관함에 저장하면 안되나?
✔️ 데이터를 만들 때 원칙이 있다.
"데이터를 사용하는 컴포넌트들 중 최상위 컴포넌트에다가 데이터를 만들어놔야함"
데이터는 위로 전송도 가능한데 복잡하고 추적이 어렵다ㅠㅡ)
🤫 그럼 부모 데이터를 바꾸고 싶을때는 어떡해...?
✔️ custom event 문법을 사용해 부모에게 데이터를 바꿔주라고 전달하자!
부모 컴포넌트에 있는 데이터를 변경하고 싶을때 요청할 수 있는 방법
자식 컴포넌트가 요청하면 부모가 받아 수정할 수 있다.
$emit('작명', 전달할자료)
$emit('작명', 전달할자료) 로 요청할 수 있다.
= 작명한 이름으로 커스텀 이벤트 전송!
@작명="바꿔야할 데이터= 내용"; 데이터 = $event
수정해야할 부분에 커스텀 이벤트명, 바꿔야 할 데이터를 저장한다.
전달할자료는 $event라는 변수 안에 담겨서 온다.
//[ Card.vue(자식컴포넌트) ]
<template>
<div>
<img :src= "원룸들.image" class="roomImg">
<h4 v-on:click="$emit('openModal',원룸들.id)">{{ 원룸들.title }}</h4>
// click할 때마다 openModal 이라는 이벤트명, 데이터 전송
<p>{{ 원룸들.price }}만원</p>
</div>
</template>
//[ App.vue(부모컴포넌트) ]
<template>
<CardRoom @openModal="모달창=true; 누른거=$event" v-bind:원룸들="원룸들[idx]" v-for="(ele,idx) in 원룸들" :key="idx"/>
// openModal 이벤트명이 실행되면 모달창 데이터는 true값으로 바꾸고,
// 누른거 라는 이벤트의 값은 보낸 원룸들.id 값으로 바꿔줘!
</template>
🤫 근데 쭉 쓰니까 너무 길어졌어...
✔️ 함수에 담아서 전달해도 된다! 대신 this.$emit()이라고 작성해야 한다!
//[ Card.vue(자식컴포넌트) ]
<template>
<div>
<h4 v-on:click="send">{{ 원룸들.title }}</h4>
</div>
</template>
<script>
export default {
name:'CardRoom',
props:{
원룸들:Object,
},
methods:{
send(){
this.$emit('openModal', this.원룸들.id )
}
}
}
</script>