vue.js - 컴포넌트 - Events, slot
사용자 정의 이벤트
- Vue에서는 자식 컴포넌트의 문제가 발생했을 때, 부모 컴포넌트로 알리는 방법은 사용자 정의 이벤트로 알릴 수 있습니다.
- 모든 Vue인스턴스는 $on(eventName)을 사용하여 이벤트를 감지하거나 $emit(eventName)을 사용하여 이벤트를 트리거합니다.
- 하지만 Vue의 $on과 $emit이 비슷하게 동작하지만 브라우저의 EventTarget API인 addEventListener, dispatchEvent와 별개입니다.
v-on을 이용한 사용자 지정 이벤트
- 부모 컴포넌트는 자식 컴포넌트가 사용되는 템플릿에 직접 v-on을 사용하여 자식 컴포넌트에서 보내진 이벤트를 들을 수 있습니다.
- v-on과 다르게 $on은 자식에서 호출한 이벤트를 감지하지 않습니다. 반드시 v-on을 템플릿에서 지정해야 감지할 수 있습니다.
<div id="counter-event-example">
<p></p>
<button-counter v-on:increment="incrementTotal"></button-counter>
<button-counter v-on:increment="incrementTotal"></button-counter>
</div>
<script>
Vue.component('button-counter', {
template: '<button v-on:click="incrementCounter"></button>',
data: function () {
return {
counter: 0
}
},
methods: {
incrementCounter: function () {
this.counter += 1
this.$emit('increment')
}
},
})
new Vue({
el: '#counter-event-example',
data: {
total: 0
},
methods: {
incrementTotal: function () {
this.total += 1
}
}
})
</script>
- 컴포넌트에서 네이티브 이벤트를 수신할 경우가 있을 수 있습니다. 이러한 경우 v-on에 .native 수식어를 이용하면 사용할 수 있습니다.
<my-component v-on:click.native="doTheThing"></my-component>
비 부모-자식 간의 통신
- 컴포넌트의 통신이 꼭 부모-자식 관계일 수는 없습니다.
- 이때 간단하게는 같이 통신할 컴포넌트가 사용할 공통 Vue인스턴스르르 만들어서 이벤트 버스를 사용할 수 있습니다.
var bus = new Vue()
// 컴포넌트 A의 메소드
bus.$emit('id-selected', 1)
// 컴포넌트 B의 created 훅
bus.$on('id-selected', function (id) {
// ...
})
- 더 복잡한 경우에는 여기를 참고하세요. 상태 관리
컴포넌트 범위
<child-component>
</child-component>
- 위와 같은 템플릿이 있는 경우 message는 자식 데이터가 아닌 부모 데이터에 바인딩됩니다.
- 상위 템플릿의 모든 내용은 상위 범위로 컴파일됩니다. 하위 템플릿의 모든 내용은 하위 범위에서 컴파일됩니다.
단일 슬롯
- 하위 컴포넌트에 최소한 하나의 slot이 없으면 부모 컨텐츠가 삭제됩니다.
- slot에 삽입할 컨텐츠가 없는 경우 대체 컨텐츠로 표현됩니다.
<div>
<h1>나는 부모 컴포넌트의 제목입니다</h1>
<my-component>
<p>이것은 원본 컨텐츠 입니다.</p>
<p>이것은 원본 중 추가 컨텐츠 입니다</p>
</my-component>
</div>
<script>
Vue.component('my-component', {
template: `
<div>
<h2>나는 자식 컴포넌트의 제목입니다</h2>
<slot>
제공된 컨텐츠가 없는 경우에만 보실 수 있습니다.
</slot>
</div>
`
})
</script>
<!-- 위 예제의 렌더링 결과입니다. -->
<div>
<h1>나는 부모 컴포넌트의 제목입니다</h1>
<div>
<h2>나는 자식 컴포넌트의 제목 입니다</h2>
<p>이것은 원본 컨텐츠 입니다.</p>
<p>이것은 원본 중 추가 컨텐츠 입니다</p>
</div>
</div>
동적 컴포넌트
- 같은 마운트 포인트를 사용하고 예약된
<component>
엘리먼트를 사용하여 여러 컴포넌트 간에 동적으로 트랜지션하고 is 속성에 동적으로 바인드 할 수 있습니다.
<component v-bind:is="currentView">
<!-- vm.currentView가 변경되면 컴포넌트가 변경됩니다! -->
</component>
<script>
var vm = new Vue({
el: '#example',
data: {
currentView: 'home'
},
components: {
home: { /* ... */ },
posts: { /* ... */ },
archive: { /* ... */ }
}
})
</script>
- 동적 컴포넌트에서 keep-alive을 이용해 트랜지션된 컴포넌트를 메모리에 유지하거나, 다시 렌더링되지 않게 할 수 있습니다. 자세한 내용은 keep-alive API문서를 확인하시면 됩니다.
ps. 찾아보고 공부하면서 정리하는 내용이라 틀릴 수 있음을 알려드립니다.
참고