[vue.js] 컴포넌트 심화
1. 컴포넌트 안에 다른 컴포넌트 사용하기
1.1. 부모 컴포넌트와 자식 컴포넌트
1.1.1. 사용법
① 사용할 컴포넌트를 import
import ComponentA from './ComponentA'
② 사용할 컴포넌트를 components에 등록
export default{
components: {
ComponentA,
ComponentC
}
}
③ html에 컴포넌트 이름으로 태그 생성
<ComponentA />
1.1.2. Props: 부모 컴포넌트에서 자식 컴포넌트로 데이터 전달
<template>
<h2>{{title}}</h2>
</template>
<script>
export default{
props: {
title: {
type: String,
default: "페이지 제목"
}
}
}
</script>
props: 부모 컴포넌트로부터 전달받은 데이터 저장
- type: 저장될 데이터의 타입
- default: 데이터가 전달되지 않았을 때의 기본값
부모 컴포넌트에서 props로 값 넣기
<ComponentA title="부모 컴포넌트에서 전달하는 값"/>
숫자, 불린, 배열, 객체, 객체의 속성을 전달할 경우 v-bind를 사용해야 함
1.1.3. 부모 컴포넌트에서 자식 컴포넌트의 이벤트 직접 발생시키기
//자식 컴포넌트
<template>
<button type="button" @click="childFunc" ref="btn">click</button>
</template>
<script>
export default{
methods: {
childFunc(){
console.log('부모 컴포넌트에서 발생시킨 이벤트');
}
}
}
</script>
ref: id와 유사(유일한 값 사용)
<template>
<child-component @send-message="sendMessage" ref="child-component"/>
</template>
<script>
import ChildComponent from './ChildComponent';
export default{
components: {ChildComponent},
mounted(){
this.$refs.child_component.$refs.btn.click();
}
}
</script>
child-component: 컴포넌트명
@send-message
- 자식 컴포넌트에서 발생한 send-message 이벤트를 부모 컴포넌트의 sendMessage 메서드에 연결
> 자식 컴포넌트가 this.$emit('send-message')를 호출하면 부모의 sendMessage 메서드가 실행됨
mounted: 컴포넌트가 DOM에 마운트된 직후 실행
this.$refs.child_component.$refs.btn.click();
- ref="child-component"로 정의된 자식 컴포넌트에 접근
.$refs.btn
- 자식 컴포넌트 내의 ref="btn"으로 정의된 요소에 접근
.click()
- 클릭 이벤트를 발생시킴
1.1.4. 부모 컴포넌트에서 자식 컴포넌트의 함수 호출
<template>
<child-component @send-message="sendMessage" ref="child_component" />
</template>
<script>
import ChildComponent from './ChildComponent2';
export default{
components: {ChildComponent},
mounted(){
this.$refs.child_component.callFromParent();
}
}
</script>
1.1.5. 부모 컴포넌트에서 자식 컴포넌트의 데이터 옵션 값 변경
<template>
<h1>{{msg}}</h1>
</template>
<script>
export default{
data(){
return{
msg: ''
};
}
}
</script>
<template>
<child-component @send-message="sendMessage" ref="child_component"/>
<button type="button" @click="changeChildData">Change Child Data</button>
</template>
<script>
import ChildComponent from './ChildComponent';
export default{
components: {ChildComponent},
methods: {
changeChildData(){
this.$refs.child_component.msg = "부모 컴포넌트가 변경한 데이터";
}
}
}
</script>
1.1.6. 자식 컴포넌트에서 부모 컴포넌트로 이벤트/데이터 전달
$emit 사용
data(){
return{
msg: '자식 컴포넌트로부터 보내는 메시지'
};
}
mounted(){
this.$emit('send-message', this.msg)
}
<template>
<child-component @send-message="sendMessage" />
</template>
<script>
import ChildComponent from './ChildComponent';
export default{
components: {ChildComponent},
methods: {
sendMessage(data){
console.log(data);
}
}
}
</script>
자식 컴포넌트가 mounted되면 $emit을 통해 부모 컴포넌트의 send-message 이벤트를 호출함
1.1.7. 부모 컴포넌트에서 자식 컴포넌트 데이터 옵션 값 동기화
<template>
<button type="button" @click="childFunc" ref="btn">자식 컴포넌트 데이터 변경</button>
</template>
<script>
export default{
data(){
return{
msg: '메시지'
};
},
methods: {
this.msg = '변경된 메시지'
}
}
</script>
<template>
<button type="button" @click="checkChild">자식 컴포넌트 데이터 조회</button>
<child-component ref="child_component" />
</template>
<script>
import ChildComponent from './ChildComponent';
export default{
components: {ChildComponent},
computed: {
msg(){
return this.$refs.child_component.msg;
}
},
methods: {
checkChild(){
alert(this.msg);
}
}
}
</script>
computed로 자식 컴포넌트의 msg 값 감지
1.2. Slot
1.2.1. slot
부모 컴포넌트에서 전달된 콘텐츠가 삽입될 위치를 지정함
부모 컴포넌트
<template>
<child-component>
<p>This is the content from the parent</p>
</child-component>
</template>
자식 컴포넌트
<template>
<div>
<h1>Title</h1>
<slot></slot>
</div>
</template>
결과 html
<div>
<h1>Title</h1>
<p>This is the content from the parent</p>
</div>
1.2.2. 이름이 있는 slot
부모 컴포넌트
<template>
<child-component>
<template #header>
<h1>Header Content</h1>
</template>
<p>Main Content</p>
<template #footer>
<p>Footer Content</p>
</template>
</child-component>
</template>
자식 컴포넌트
<template>
<div>
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
결과 html
<div>
<header>
<h1>Header Content</h1>
</header>
<main>
<p>Main Content</p>
</main>
<footer>
<p>Footer Content</p>
</footer>
</div>
1.3. Provide/Inject