Vue 컴포넌트
컴포넌트 Vue 어플리케이션에서 코드를 재사용할 수 있는 기본 단위입니다. 각각의 컴포넌트는 특정한기능과 템플릿을 갖고, 데이터와 메서드를 정의하여 독립적으로 동작할 수 있습니다. 컴포넌트를 이용하면 HTML 요소들을 확장하고 화면을 구조화함으로 코드를 캡슐화하여 재사용 및 유지보수를 용이하게 해줍니다.
Vue 컴포넌트 작성
<template>
<div>
<h2>{{ title }}</h2>
<p>{{ count }}</p>
<button @click="incrementCount">Count 증가</button>
</div>
</template>
<script>
export default {
data() {
return {
title: "Component",
count: 0
};
},
methods: {
incrementCount() {
this.count++;
}
}
}
</script>
Vue 컴포넌트 등록
전역 등록
main.js:
import Vue from 'vue';
import GlobalComponent from './components/GlobalComponent.vue';
Vue.component('global-component', GlobalComponent);
new Vue({
// 루트 Vue 인스턴스 옵션들
// ...
}).$mount('#app');
- `Vue.component('component-name', { options });
- `component-name`: 다른 인스턴스 template에서 사용될 태그 이름이 됩니다.
- `component-name` 명명 규칙은 [소문자 + 케밥 기법(하이픈)] 입니다.
- `options`: `data`, `methods`, `computed`, `props`, `watch` 등
- `Vue.component`를 사용하여 등록한 컴포넌트는 어플리케이션 전체에서 사용할 수 있습니다. 위 예제에서는 GlobalComponent.vue 컴포넌트를 등록하였고, `<global-component`> 태그를 어디서든 사용할 수 있습니다.
- 루트 Vue 인스턴스를 인스턴스화하기 전에 전역 컴포넌트를 등록해주어야 사용 가능합니다.
💁♂️ `main.js`:
Vue.js 어플리케이션의 진입점, 어플리케이션을 초기화하고 루트 Vue 인스턴스를 생성하는 파일로 어플리케이션의 전역 설정이나 초기화 로직 등을 이곳에서 처리합니다.
1. Vue 라이브러리 및 필요한 플러그인을 import 합니다.
2. 루트 Vue 인스턴스를 생성하고, 루트 컴포넌트(`App.vue`)를 등록합니다.
3. 루트 인스턴스를 DOM에 마운트하여 어플리케이션을 렌더링합니다.
💁♂️ `App.vue`:
루트 컴포넌트로서, Vue.js 어플리케이션에서 가장 최상위에 위치하는 컴포넌트입니다.
해당 컴포넌트로 어플리케이션의 전체 레이아웃과 구조를 정의(공통 레이아웃, 헤더, 푸터 등의 구성 요소)하며, 하위에 다른 컴포넌트들을 포함할 수 있습니다.
추가로 보통 `라우터 뷰(<router-view>)를 통해 다른 페이지 컴포넌트들을 동적으로 렌더링 합니다.
☞ `main.js`가 먼저 실행되어 Vue 인스턴스를 초기화하고, 그 다음에 `App.vue`가 루트 컴포넌트로 등록되어 어플리케이션의 기본 구조를 구성합니다.
지역 등록
<template>
<div>
<!-- 지역으로 등록된 LocalComponent 사용 -->
<local-component></local-component>
</div>
</template>
<script>
import LocalComponent from './LocalComponent.vue';
export default {
components: {
'local-component': LocalComponent
}
}
</script>
- 해당 인스턴스에서만 유효한 범위를 갖습니다.
- 인스턴스에 components 속성을 추가하고 등록할 컴포넌트 이름과 내용을 정의하면 됩니다.
뷰 컴포넌트 간 통신: Props & Emit & Event Bus
JS로 화면을 구성할 때 한 화면의 데이터를 해당 화면 영역 어디서든지 호출할 수가 있습니다. 이는 한 화면을 1개의 뷰(View) 단위로 간주하였기 때문입니다. 하지만 Vue.js는 컴포넌트로 화면을 구성하고, 각 컴포넌트의 유효 범위가 독립적이기 때문에 직접 다른 컴포넌트의 값을 참조할 수 없습니다. 따라서 같은 웹 페이지라도 데이터를 공유할 수 없습니다.
다른 컴포넌트의 값을 참조하기 위해선 컴포넌트 간 통신 방법을 알아야 합니다.
부모-자식 관계에 있는 컴포넌트들은 다음 두 가지 속성을 사용하여 데이터를 전달할 수 있습니다.
- props: 상위에서 하위로 데이터를 전달하는 속성입니다.
- emit events: 하위에서 상위로 메소드를 호출하는 속성입니다.
props 속성: 상위에서 하위로
상위 컴포넌트:
<template>
<div>
<child-component :message="messageFromParent" />
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
data() {
return {
messageFromParent: "Hello from Parent!"
};
},
components: {
ChildComponent
}
}
</script>
상위 컴포넌트에서 하위 컴포넌트로 Props를 전달할 때는 `v-bind`( `:` )를 사용하여 Props를 정의합니다.
하위 컴포넌트:
<template>
<div>
<p>{{ message }}</p>
</div>
</template>
<script>
export default {
props: ['message']
}
</script>
하위 컴포넌트에서 전달받은 Props를 사용할 때는 `props` 옵션을 이용하여 Props를 정의합니다.
※ 컴포넌트 등록에 따른 관계
인스턴스에 새로운 컴포넌트를 등록하면 기존에 있던 컴포넌트는 상위 컴포넌트가 되고, 새로 등록된 컴포넌트는 하위 컴포넌트가 됩니다.
emit events: 하위에서 상위로
props 속성은 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달하는 방식으로 통신하였다면,
하위 컴포넌트에서 상위 컴포넌트로 통신하는 방식은 하위에서 이벤트를 발생시키고 상위에서 이벤트를 수신하여 상위의 메서드를 호출하는 방식으로 통신합니다.
props 속성을 설명할 때는 데이터를 전달한다고 표현하고 emit events를 설명할 때는 이벤트를 발생시켜 신호를 보낸다는 표현을 보면 알 수 있듯이, emit events 방식에서는 하위에서 상위로 데이터를 전달하는 방법이 없습니다.
그럼에도 하위에서 상위로 데이터를 전달하고 싶다면, 이벤트 버스(Event Bus)를 이용하여 이벤트 인자로 데이터를 전달하는 방법이 있습니다. 이 부분은 후에 다루도록 하겠습니다.
하위 컴포넌트:
<template>
<button @click="onButtonClick">Click</button>
</template>
<script>
export default {
methods: {
onButtonClick() {
this.$emit('button-click', 'Button click!');
}
}
}
</script>
하위 컴포넌트에서 상위 컴포넌트로 이벤트를 발생시키기위해서는 `this.$emit()` 메서드를 사용합니다.
- `this.$emit('이벤트명')`: 이벤트만 발생시키는 경우
- `this.$emit('이벤트명', '인자')`: 인자를 함께 전달하여 이벤트를 발생시키는 경우
상위 컴포넌트:
<template>
<div>
<child-component @button-click="handleButtonClick" />
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
methods: {
handleButtonClick(message) {
console.log(message); // "Button click!"
}
}
}
</script>
상위 컴포넌트에서 하위 컴포넌트로부터 발생한 이벤트를 감지하고 처리하기 위해서는 `v-on`( `@` )을 사용하여 이벤트를 수신할 할 수 있습니다.
같은 레벨 컴포넌트 간 통신
Vue.js는 상위에서 하위로만 데이터를 전달하는 통신 규칙을 따르기 때문에 바로 옆 컴포넌트에 값을 전달하기 위해서는 하위 컴포넌트에서 공통 상위 컴포넌트로 이벤트를 전달한 후, 공통 상위 컴포넌트에서 2개의 하위 컴포넌트에 props를 사용해 데이터를 전달하여야 합니다. 이런 방식을 사용하면 상위 컴포넌트가 필요 없는 경우에도 같은 레벨 간 통신을 위해 상위 컴포넌트를 두어야 하는 번거로움이 있습니다. 이러한 문제는 이벤트 버스(Event Bus)를 이용해 해결할 수 있습니다.
Event Bus: 모든 컴포넌트 간 통신
이벤트 버스를 사용함으로 개발자가 지정한 2개의 컴포넌트 간에 데이터를 주고받을 수 있습니다. 때문에 다음과 같은 관계에서도 데이터를 서로 전달할 수 있습니다.
- 하위 컴포넌트에서 상위 컴포넌트로 데이터 전달
- 같은 레벨 컴포넌트 간 데이터 전달 (공통 상위 컴포넌트 없이)
- 관계 없는 컴포넌트 간 데이터 전달
event-bus.js:
import Vue from 'vue';
export const eventBus = new Vue();
위 처럼 별도의 파일을 만들어서 다른 컴포넌트에서 import하여 사용할 수 있습니다. 물론 `main.js`나 최상위 파일에서 Event Bus를 생성하고 내보내 전역적으로 사용할 수 있습니다.
이벤트 발행:
import { eventBus } from './eventBus';
export default {
methods: {
onButtonClick() {
// 'button-click'라는 이벤트를 발행하고 인자로 데이터 'Button click'를 함께 전달
eventBus.$emit('button-click', 'Button click');
}
}
}
이벤트 수신:
import { eventBus } from './eventBus';
export default {
created() {
// 'button-click' 이벤트를 구독하고, 발생 시 handleButtonClick 메서드를 실행
eventBus.$on('button-click', this.handleButtonClick);
},
methods: {
handleButtonClick(message) {
console.log(message); // "Button click"
}
}
}
'Front-End > Vue.js' 카테고리의 다른 글
Vue.js 디렉티브(v-접두사) (0) | 2023.05.11 |
---|---|
Vue.js axios를 이용한 HTTP 통신 (0) | 2023.05.11 |
Vue.js Router로 싱글 페이지 어플리케이션(SPA) 페이지 라우팅 구현 (0) | 2023.05.10 |
Vue.js 뷰 인스턴스와 인스턴스 라이프 사이클 (0) | 2023.05.10 |
Vue.js 우편번호 서비스 연동하기 (Daum 우편번호) (0) | 2023.02.15 |