일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 자바스크립트
- CSS
- input
- event
- App.vue
- Vue
- v-html
- react
- Vue transition
- storybook
- vuex
- ES6
- MySQL
- scss
- Vue.js
- express
- Wecode
- 자료구조
- jsx
- TypeScript
- 쉬운설명
- mapGetters
- nodejs
- State
- HOC
- sass
- JavaScript
- 리액트
- webpack
- 댓글달기
- Today
- Total
익명의 개발노트
[vue.js] high-order-component과 Mixin 본문
1. 스피너 같은거는 이벤트 버스로 통제해주는 것이 간결하다.
버스는 라이프 싸이클 내부에서 사용
이벤트 on했으면 off도 반드시 해주어야함,
2. 하이오더 컴포넌트
1) 컴포넌트의 코드를 재사용할 수 있는 기술
2) 단점: HOC로 통신하는 것이 많을 수록 컴포넌트 레벨이 깊어지면서 컴포넌트 통신에있어서 불편한 현상들이 발생함.
ex) ask, jobs, news컴포넌트에서 api 콜하는 부분이 코드가 똑같다.(엔드포인트 주소는 다름)
//ask.vue
created() {
Bus.$emit("start:spinner");
setTimeout(() => {
this.$store
.dispatch("FETCH_ASK")
.then(() => {
Bus.$emit("end:spinner");
})
.catch(error => {
console.log(error);
});
}, 3000);
}
//jobs.vue
created() {
Bus.$emit("start:spinner");
setTimeout(() => {
this.$store
.dispatch("FETCH_JOBS")
.then(() => {
Bus.$emit("end:spinner");
})
.catch(error => {
console.log(error);
});
}, 3000);
}
//news.vue
created() {
Bus.$emit("start:spinner");
setTimeout(() => {
this.$store
.dispatch("FETCH_NEWS")
.then(() => {
Bus.$emit("end:spinner");
})
.catch(error => {
console.log(error);
});
}, 3000);
}
위 코드는 각 페이지 이동시 로딩바(스피너) 실행 후 3초후 데이터를 백엔드(리스트 보여지는 부분) 에서 받아와서 Vuex에 저장한 코드다.
위 코드를 HOC로 변경해보자.
1. src/view 폴더 안에 ListView를 만든다.
//ListView
<template>
<list-item></list-item>
</template>
<script>
import ListItem from "../components/ListItem.vue";
export default {
components: {
ListItem
}
};
</script>
<style>
</style>
2. src/view 폴더안에 CreateListView.js파일을 만들고 공통되는 부분을 작성한다.
//하이오더 컴포넌트(CreateListView.js)
import ListView from "./ListView.vue";
import Bus from "../utils/bus.js";
export default function createListView(name) {
return {
//재사용할 인스턴스(컴포넌트) 옵션들이 들어갈 자리
name: name, //'NewsView' ,'JobsView' ,'AskView'
created() {
Bus.$emit("start:spinner");
setTimeout(() => {
this.$store
.dispatch("FETCH_LIST", this.$route.name)
.then(() => {
Bus.$emit("end:spinner");
})
.catch(error => {
console.log(error);
});
}, 3000);
},
render(createElement) {
return createElement(ListView);
}
};
}
3. 실제 클릭하면 이동하는 부분인 라우터 쪽을 수정한다.
//src/routes/index.js
import createListView from "../views/CreateListView.js";
export const router = new VueRouter({
mode: "history", //url # 제거
routes: [
{
path: "/",
redirect: "/news"
},
{
//path: url주소
//component : url 주소로 갔을때 컴포넌트
path: "/news",
name: "news",
component: NewsView
},
{
path: "/jobs",
name: "jobs",
component: JobsView
},
{
path: "/ask",
name: "ask",
component: AskView
},
]
}
위 라우터 파일을 아래와 같이 변경한다.
import createListView from "../views/CreateListView.js";
export const router = new VueRouter({
mode: "history", //url # 제거
routes: [
{
path: "/",
redirect: "/news"
},
{
//path: url주소
//component : url 주소로 갔을때 컴포넌트
path: "/news",
name: "news",
component: createListView("NewsView") //하이오더 컴포넌트 적용
},
{
path: "/jobs",
name: "jobs",
component: createListView("JobsView")
},
{
path: "/ask",
name: "ask",
component: createListView("AskView")
},
]
}
컴포넌트에 CreateListView 를 정하고 입력한 컴포넌트의 이름을 값으로 넘겨준다.
//CreateListView.js
//하이오더 컴포넌트
import ListView from "./ListView.vue";
import Bus from "../utils/bus.js";
export default function createListView(name) {
return {
//재사용할 인스턴스(컴포넌트) 옵션들이 들어갈 자리
name: name, //'NewsView' ,'JobsView' ,'AskView'
created() {
Bus.$emit("start:spinner");
setTimeout(() => {
this.$store
.dispatch("FETCH_LIST", this.$route.name)
.then(() => {
Bus.$emit("end:spinner");
})
.catch(error => {
console.log(error);
});
}, 3000);
},
render(createElement) {
return createElement(ListView);
}
};
}
라우터에서 컴포넌트 이름을 넘겨주고 HOC에서 받아와서, this.$route.name으로 라우터 이름 달아주고,
보여주고자 하는 컴포넌트 ListView를 랜더부분에 넣어주면된다.
4. Vuex의 Action, Mutations를 수정해준다. (애초에 Vuex에 데이터를 저장하기 때문에)
//action.js
import {
fetchNewsList,
fetchAskList,
fetchJobsList,
fetchUserInfo,
fetchCommentItem,
} from "../api/index.js";
export default {
FETCH_NEWS(context){
fetchNewsList()
.then(res => {
console.log(res);
context.commit('SET_NEWS', res.data);
return res; //spinner off해야함.
})
.catch(error => {
console.log(error);
})
},
FETCH_ASK(context){
fetchAskList()
.then(res => {
console.log(res);
context.commit('SET_ASK', res.data);
})
.catch(error => {
console.log(error);
})
},
FETCH_JOB({commit}){
fetchJobsList()
.then(res => {
console.log(res);
commit('SET_JOB', res.data);
})
.catch(error => {
console.log(error);
})
},
FETCH_USER({commit}, name){
fetchUserInfo(name)
.then( ({data}) => {
commit('SET_USER', data);
})
.catch(error => {
console.log(error);
})
},
FETCH_ITEM({commit}, id){
fetchCommentItem(id)
.then( ({data}) => {
commit('SET_ITEM', data);
})
.catch(error => {
console.log(error);
})
},
}
위의 코드에서 FETCH_LIST를 추가하고 state에 list를 추가한다.
//src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import mutations from './mutations.js';
import actions from './actions';
Vue.use(Vuex)
export const store = new Vuex.Store({
state: {
news:[],
asks:[],
jobs:[],
user:{},
item:[],
list:[],//추가
},
//getters는 컴포넌트의 computed임. 더 간결하게 쓰기위해서 스토어에 명시
getters:{
fetchedAsk(state){
return state.asks;
},
fetchedItem(state){
return state.item;
}
},
//mutations:mutations, //같으니깐 mutations하나로 해도됨.
mutations,
actions,
})
//action.js
import {
(...중략)
fetchList
} from "../api/index.js";
export default {
(... 중략)
FETCH_LIST({commit}, pageName){
fetchList(pageName)
.then(({data}) => commit('SET_LIST',data))
.catch(error => console.log(error));
}
}
mutations.js에 SET_LIST 추가한다.
//mutations.js
export default {
SET_NEWS(state, news){
state.news = news;
},
SET_ASK(state, ask){
state.asks = ask;
},
SET_JOB(state, jobs){
state.jobs = jobs;
},
SET_USER(state, user){
state.user = user;
},
SET_ITEM(state, item){
state.item = item;
},
SET_LIST(state, list){
state.list = list;
},
}
데이터가 잘 나오는지 확인하면 끝.
공통적인 부분은 HOC로 만들어주고 거기서 네임이든 분기처리를 해주면된다.
5. Mixins
1) Mixins으로 공통되는 부분을 뺄 수도 있다. 스피너 같은 부수적인 요소들을 빼면 굉장히 심플해진다.
때에 따라서는 CRUD도 뺄 수 있다.
2) HOC보다 레이어가 얕음.(HOC: newsView -> listView -> listItem / Mixins : newsView -> listItem)
3) src 밑에 mixins폴더 생성 후 공통으로 사용하고자 하는 코드를 옮긴다.
//ListMixin.js
import Bus from "../utils/bus.js";
export default {
//재사용할 컴포넌트 & 옵션
created() {
Bus.$emit("start:spinner");
setTimeout(() => {
this.$store
.dispatch("FETCH_LIST", this.$route.name)
.then(() => {
Bus.$emit("end:spinner");
})
.catch(error => {
console.log(error);
});
}, 3000);
},
}
//newsView.vue
<template>
<div>
<list-item></list-item>
</div>
</template>
<script>
import ListItem from "../components/ListItem.vue";
import ListMixins from "../mixins/ListMixin.js";
export default {
components: {
ListItem
},
mixins:[ListMixins],
};
</script>
//routes/index.js
import NewsView from "../views/NewsView.vue";
import AskView from "../views/AskView.vue";
import JobsView from "../views/JobsView.vue";
export const router = new VueRouter({
mode: "history", //url # 제거
routes: [
{
path: "/",
redirect: "/news"
},
{
//path: url주소
//component : url 주소로 갔을때 컴포넌트
path: "/news",
name: "news",
component: NewsView
},
{
path: "/jobs",
name: "jobs",
component: JobsView
},
{
path: "/ask",
name: "ask",
component: AskView
},
]
});
'코딩일기 > TIL' 카테고리의 다른 글
[typescript] vuex (0) | 2020.01.05 |
---|---|
[typescript] Vue 클래스 기반 컴포넌트 만드는 법, Prop 전달하는 방법 (0) | 2020.01.03 |
[vue.js] 공통부분 컴포넌트 처리 & Slot & slot-scope (0) | 2019.12.24 |
[vue.js] 동적 라우팅 & v-html & 트랜지션 (0) | 2019.12.23 |
[terminal] mac iterm2 + zsh로 터미널 만들기 (1) | 2019.12.20 |