반응형
컴포넌트 디자인 패턴
1. Common - 기본적인 컴포넌트 등록과 컴포넌트 통신
<App.vue>
<template>
<div id="app">
<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>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
<AppHeader.vue>
<template>
<div>
<h1>{{ title }}</h1>
</div>
</template>
<script>
export default {
// 기존 props 방식
// props: ['title']
// Props Validation
props:{
title: String,
}
};
</script>
<style lang="scss" scoped>
</style>
<AppContent.vue>
<template>
<div>
<ul>
<li v-for="(item, idx) in items" v-bind:key="idx">
{{item}}
</li>
</ul>
<!-- 메서드 안만들고 클릭하자마자 상위 컴포넌트로 이벤트 올려보내기 가능 -->
<button @click="$emit('renew')">renew items</button>
</div>
</template>
<script>
export default {
// Props Validation
// array 가 아닌 데이터가 들어오면 에러처리
props:{
items:{
type: Array,
required: true,
}
}
};
</script>
<style lang="scss" scoped>
</style>
2. Slot - 마크업 확장이 가능한 컴포넌트
slot은 데이터는 위에있음 아래 컴포넌트에서 데이터를 표현만 해줄뿐
slot을 왜 쓸까?
- 요구사항이 바뀔때를 대비, 유연하게 화면의 영역을 확장 할 수 있다.
<App.vue>
<template>
<div>
<ul>
<!-- 기존 컴포넌트는 이런 모양 <app-header></app-header> -->
<!-- slot은 props 안내려도 v-for로 데이터 출력 가능 -->
<item v-for="(item, idx) in items" v-bind:key="idx">{{ item }}</item>
<item>
<!-- slot의 장점 -->
<!-- 만약 요구사항이 바뀔때 유연하게 대처 가능, 모델 마음대로 확장 가능 -->
아이템 1
</item>
<item>
<!-- 2. 버튼을 넣어주세요 -->
아이템 2
<button>click me</button>
</item>
<item>
<!-- 3. 텍스트와 함께 이미지를 표현해주세요 -->
<div>
아이템 3
</div>
<img src="./assets/f7.png" alt="">
</item>
<item>
<!-- 4. slot에는 style도 넣을수 있단 -->
<div style="color: blue; font-size: 20px;">
아이템 4
</div>
</item>
<!-- <item v-for="(item, idx) in items" v-bind:key="idx" :item="item"></item> -->
</ul>
</div>
</template>
<script>
import Item from './Item.vue'
export default {
components:{
Item,
},
data() {
return {
items: ['slot 1', 'slot 2', 'slot 3', 'slot 4', 'slot 5']
};
},
};
</script>
<style lang="scss" scoped>
</style>
<Item.vue>
<template>
<li>
<slot>
<!-- 등록하는 곳에서 정의할 화면 영역 -->
<!-- {{ item }} -->
</slot>
</li>
</template>
<script>
export default{
// props: ['item']
}
</script>
3. Controlled - 결합력이 높은 컴포넌트
- 하위에서 관리해야 했던 데이터를 상위에서 관리하게 하는 방법
- 컴포넌트에 데이터 의존성 분리
<App.vue>
<template>
<!-- <check-box :checked="checked"></check-box> -->
<div>
<check-box v-model="checked"></check-box>
</div>
</template>
<!-- <script src="http://code.jquery.com/jquery-latest.min.js"></script> -->
<script>
import CheckBox from './components/CheckBox.vue'
export default {
// @input 이벤트
// :value 값
components:{
CheckBox,
},
data(){
return{
checked: false,
}
},
};
</script>
<style scoped>
</style>
<CheckBox.vue>
<template>
<div>
<!-- <input type="checkbox" v-model="checked"> -->
<input type="checkbox" :value="value" @click="toggleCheckBox"></input>
</div>
</template>
<script>
export default {
// props: ['checked'],
// @input 이벤트
// :value 값
props: ['value'],
methods: {
toggleCheckBox() {
this.$emit('input', !this.value) // true로 올리는것보단 반대로 되야하니까 not!
},
},
};
</script>
<style lang="scss" scoped>
</style>
4. Renderless - 데이터 처리 컴포넌트
<App.vue>
<template>
<div>
<fatch-data url="https://jsonplaceholder.typicode.com/users/1">
<!-- reader 함수로 이곳에 값이 노출 -->
<div slot-scope="{response, loading}" v-if="!loading">
{{ response }}
<div v-if="loading">
loading...
</div>
</div>
</fatch-data>
</div>
</template>
<script>
import FatchData from './components/FetchData.vue'
export default {
components: {
FatchData
},
};
</script>
<style lang="scss" scoped>
</style>
<FetchData.vue>
<template>
<div>
<p>name : {{ response.name }}</p>
<p>email : {{ response.email }}</p>
</div>
</template>
<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(erorr=>{
alert('[ERROR] fetching the data', error);
console.log(erorr);
});
},
// render 함수는? - 컴포넌트를 그리는것, 컴포넌트 표현 - 데이터만 넘겨줌. response, loading 넘겨줌, 노출 - 상위 컴포넌트 등록한곳에
// $scopedSlots.default 는? - 하위컴포넌트 데이터를 상위에 노출 시키는것 상위에서 접근할수 있게하는것
render(){
return this.$scopedSlots.default({
response: this.response,
loading: this.loading
})
}
};
</script>
<style lang="scss" scoped>
</style>
반응형
'vue.js > vue.js 2' 카테고리의 다른 글
77. 서비스 배포를 위한 명령어 소개 및 실습 | CLI로 생성한 프로젝트 배포하기 (0) | 2022.10.02 |
---|---|
76. render 함수 (0) | 2022.08.21 |
74. refs 속성 (0) | 2022.08.13 |
73. chart.js 라이브러리 사용 (0) | 2022.08.13 |
72. chart.js 라이브러리 설치 (0) | 2022.08.13 |