728x90
반응형
Component Design Patterns
1. Common : 기본적인 컴포넌트 등록과 컴포넌트 통신
일반적인 컴포넌트 사용 패턴으로 상위 컴포넌트와 하위 컴포넌트 간 props 속성
과 Event emit
을 사용하여 통신하는 방법
예제
- App.vue
<template>
<div>
<!-- 일반적인 컴포넌트 사용 방식 -->
<!-- props 속성, event emit 사용 하여 데이터 통신 -->
<app-header :title="appTitle"></app-header>
<app-content :items="items" @renew="renewItems"></app-content>
</div>
</template>
<script>
import AppHeader from "./components/AppHeader.vue";
import AppContent from "./components/AppContent.vue";
export default {
components: {
AppHeader,
AppContent,
},
data() {
return {
appTitle: "Common Approach",
items: [10, 20, 30],
};
},
methods: {
renewItems() {
this.items = [40, 50, 60];
},
},
};
</script>
- AppHeader.vue
<template>
<header>
<h1>{{ title }}</h1>
</header>
</template>
<script>
export default {
props: {
title: String,
},
};
</script>
- AppContent.vue
<template>
<div>
<ul>
<li v-for="(item, i) in items" v-bind:key="i">
{{ item }}
</li>
</ul>
<button @click="$emit('renew')">renew items</button>
</div>
</template>
<script>
export default {
props: {
items: {
type: Array,
required: true,
},
},
};
</script>
결과
2. Slot : 마크업 확장이 가능한 컴포넌트
마크업 확장 컴포넌트를 구성하는 패턴
예제
- App.vue
<template>
<div>
<ul>
<item>
<!-- slot 에 들어갈 내용 -->
아이템 1
</item>
<item>
아이템 2 <button>click me</button>
</item>
<item>
<div>아이템 3</div>
<img src="./assets/unnamed.png" alt="스누피" width="50px" height="50px">
</item>
<item>
<div style="color: blue; font-size: 20px;">아이템 4</div>
</item>
</ul>
</div>
</template>
<script>
import Item from './Item.vue';
export default {
components: {
Item,
},
}
</script>
- Item.vue
<template>
<li>
<slot>
<!-- 등록하는 곳(상위 컴포넌트)에서 정의할 화면 영역 -->
</slot>
</li>
</template>
결과
3. Controlled : 결합력이 높은 컴포넌트
컴포넌트를 세밀하게 나눌 때 사용하는 패턴으로 상위 컴포넌트에서 하위 컴포넌트의 데이터를 관리하고, 하위 컴포넌트에서 Event emit
을 통해 상위 컴포넌트에 전달하여 데이터 변화를 주는 방법
예제
- App.vue
<template>
<!-- 상위 컴포넌트에서 데이터 관리 -->
<!-- v-model 은 내부에서 input 이라는 이벤트와 value 라는 데이터를 통해 값을 바꾸고 있다 -->
<check-box v-model="checked"></check-box>
</template>
<script>
import CheckBox from "./components/CheckBox.vue";
export default {
components: {
CheckBox,
},
data() {
return {
checked: false,
};
},
};
</script>
- CheckBox.vue
<template>
<input type="checkbox" :value="value" @click="toggleCheckBox" />
</template>
<script>
export default {
// v-model 은 내부에서 input 이라는 이벤트와 value 라는 데이터를 통해 값을 변경한다.
// @input 이벤트
// :value 값
// v-model 은 내부에서 value 라는 데이터를 사용
props: ["value"],
methods: {
toggleCheckBox() {
// 상위 컴포넌트로 이벤트 전달
// v-model 은 내부에서 input 이라는 이벤트 사용
this.$emit("input", !this.value);
},
},
};
</script>
결과
4. Renderless : 데이터 처리 컴포넌트
표현을 하지 않는 컴포넌트, 데이터 제공만 하는 컴포넌트를 구성하는 패턴으로 render()
를 이용하여 화면을 구성하는 방법
예제
- App.vue
<template>
<div>
<fetch-data url="https://jsonplaceholder.typicode.com/users/1">
<!-- slot-scope 선언된 태그 내에서만 response, loading 접근 가능 -->
<div slot-scope="{ response, loading }">
<div v-if="!loading">
<p>name: {{ response.name }}</p>
<p>email: {{ response.email }}</p>
</div>
<div v-if="loading">
Loading...
</div>
</div>
</fetch-data>
</div>
</template>
<script>
import FetchData from "./components/FetchData.vue";
export default {
name: "app",
components: {
FetchData,
},
};
</script>
- FetchData.vue
<script>
import axios from 'axios';
export default {
props: ['url'],
data() {
return {
response: null,
loading: true,
}
},
created() {
axios.get(this.url)
.then(response => {
this.response = response.data;
this.loading = false;
})
.catch(error => {
alert('[ERROR] fetching the data', error);
console.log(error);
});
},
render() {
// $scopedSlots : 등록한 하위 컴포넌트의 데이터
// 유연하게 컴포넌트 설계 가능
return this.$scopedSlots.default({
response: this.response,
loading: this.loading,
});
},
}
</script>
결과
※ Render Function
render()
함수 사용 예제
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Render Function</title>
</head>
<body>
<div id="app">
<!-- 인스턴스 영역 -->
<!-- <p>{{ message }}</p> -->
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
message: "Hello Vue",
},
// template: '<p>{{ message }}</p>',
render: function(createElement) {
// return createElement('태그 이름', '태그 속성', '하위 태그 내용');
return createElement('p', this.message);
}
});
</script>
</body>
</html>
결과
main.js
에서 render()
함수 표현 방법
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
// 1
// render: function(createElement) {
// return createElement(App);
// },
// 2
// Vue.js 는 Virtual DOM 사용
// 따라서 createElement -> HyperScript의 약자인 h로 줄여서 쓴다.
// render: function(h) {
// return h(App);
// },
// 3
// Arrow Function 사용
// render: (h) => {
// return h(App);
// },
// 4
// render : h => h(App),
}).$mount('#app')
참고
v3.vuejs.org/guide/render-function.html
728x90
반응형
'Dev > Vue.js' 카테고리의 다른 글
[Vue.js] Today I Learned 소개 (0) | 2020.10.07 |
---|---|
[Vue.js] Hacker News - 서비스 배포 환경 구성 (0) | 2020.10.07 |
[Vue.js] Hacker News - 외부 라이브러리 모듈화 (0) | 2020.10.05 |
[Vue.js] Hacker News - Async & Await를 이용한 비동기 처리 (0) | 2020.09.25 |
[Vue.js] Hacker News - 데이터 호출과 UX (0) | 2020.09.25 |
댓글