반응형
vue의 하이 오더 컴포넌트는 리액트의 하이 오터 컴포넌트에서 기원된 것입니다.
리액트의 하이 오더 컴포넌트 소개 페이지를 보면
아래와 같이 정확한 정의가 나와 있습니다.
A higher-order-component (HOC) is an advanced technique in React for reusing component logic.
이 말을 정리해보면 다음과 같습니다.
하이 오더 컴포넌트의 컴포넌트의 로직(코드)을 재사용하기 위한 고급 기술 입니다.
1. 공통적으로 사용하는 로직을 컴포넌트 하나에 올리고
2. 그 컴포넌트를 내려받아 사용
routes 폴더 <index.js>
import Vue from 'vue'
import VueRouter from 'vue-router'
import ItemView from '../views/ItemView.vue'
import UserView from '../views/UserView.vue'
import createListView from '../views/CreateListView'
Vue.use(VueRouter);
export const router = new VueRouter({
mode: 'history', // url #값 제거
routes: [ //routes도 커졌을때 모듈화 가능
{
path: '/',// url에 대한 정보가 담기는곳, url주소
redirect: '/news',// url 주소로 갔을때 표시될 컴포넌트
},
{
path: '/news',
name: 'news',
component: createListView('NewsView'),
// 하이 오더 컴포넌트
// 기존에 있던 컴포넌트 위에 컴포넌트가 하나 더 생김
},
{
path: '/ask',
name: 'ask',
component: createListView('AskView'),
},
{
path: '/jobs',
name: 'jobs',
component: createListView('JobsView'),
},
{
path: '/item/:id',
component: ItemView,
},
{
path: '/user/:id',
component: UserView,
},
]
});
api 폴더 <index.js>
import axios from 'axios';
// 1. HTTP Requset & Response 와 관련된 기본 설정
const config = {
baseUrl: 'https://api.hnpwa.com/v0/'
};
// 2. 공통 API 함수들 정리
function fetchNewsList(){
// return 바로 해준게 핵심
// return axios.get(config.baseUrl+'/news/1.json');
return axios.get(`${config.baseUrl}news/1.json`);
}
function fetchJobsList(){
return axios.get(`${config.baseUrl}jobs/1.json`)
}
function fetchAskList() {
return axios.get(`${config.baseUrl}ask/1.json`)
}
// 하이 오더 컴포넌트 용
function fetchList(pageName) {
return axios.get(`${config.baseUrl}${pageName}.json`)
}
function fetchUserInfo(username){
// https://api.hnpwa.com/v0/user/32340433.json
return axios.get(`${config.baseUrl}user/${username}.json`)
}
function fetchCommentItem(id){
// https://api.hnpwa.com/v0/item/32340433.json
return axios.get(`${config.baseUrl}item/${id}.json`)
}
// 3. 마지막 내보내기
export { fetchNewsList, fetchJobsList, fetchAskList, fetchUserInfo, fetchCommentItem, fetchList }
<action.js>
import { fetchNewsList, fetchAskList, fetchJobsList, fetchUserInfo, fetchCommentItem, fetchList } from '../api/index.js'
export default { // 1. 백엔드 API를 actions으로 받고
// FETCH_NEWS(context) {
// fetchNewsList()
// .then(res => {
// context.commit('SET_NEWS', res.data);
// return res;
// })
// .catch(error => console.log(error));
// },
// FETCH_ASKS({ commit }) {
// fetchAskList()
// .then(({ data }) => {
// commit('SET_ASKS', data);
// })
// .catch(error => console.log(error))
// },
// FETCH_JOBS({ commit }) {
// fetchJobsList()
// .then(({ data }) => {
// commit('SET_JBOS', 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({ commit }, pageName){
fetchList(pageName)
.then(({data}) => {
commit('SET_LIST', data)
})
.catch(error => console.log(error))
}
}
<mutation.js>
export default{ // 2. mutations으로 데이터 받아서
// SET_NEWS(state, data) {
// state.news = data;
// },
// SET_ASKS(state, data) {
// state.asks = data;
// },
// SET_JBOS(state, data) {
// state.jobs = data;
// },
SET_USER(state, data){
state.user = data;
},
SET_ITEM(state, data){
state.items = data;
},
SET_LIST(state, data){
state.list = data;
}
}
store 폴더 <index.js>
import Vue from 'vue'
import Vuex from 'vuex'
import mutations from './mutation.js';
import actions from './action.js'
Vue.use(Vuex);
// vuex는 상태관리 도구
// 상태는 여러 컴포넌트 간에 공유되는 데이터 속성
export const store = new Vuex.Store({
state : { // 3. state에 저장한다.
// news : [],
// asks : [],
// jobs : [],
user : {},
items: {},
list: [],
},
getters:{
fetchedNews(state) {
return state.news
},
fetchedAsk(state){
return state.asks
},
fetchedJobs(state){
return state.jobs
},
fetchedItem(state){
return state.items
}
},
mutations, // 2. mutations으로 데이터 받아
actions // 1. 백엔드 API를 actions으로 받고
})
<CreateListView.js>
import ListView from './ListView.vue';
import bus from '../utils/bus.js'
export default function createListView(name){
return{
// 재사용할 인스턴스(컴포넌트) 옵션들이 들어갈 자리
name: name,
created(){
bus.$emit('start:spinner');
this.$store.dispatch('FETCH_LIST', this.$route.name)
.then(() => {
console.log('fetched')
bus.$emit('end:spinner');
})
.catch((error) => {
console.log(error);
});
},
render(createElement){
return createElement(ListView);
}
}
}
<ListView.vue>
<template>
<div>
<list-item></list-item>
</div>
</template>
<script>
import listItem from '../components/listItem.vue';
export default {
components:{
listItem
}
};
</script>
<style lang="scss" scoped>
</style>
<listItem.vue>
<template>
<div>
<ul class="news-list">
<li v-for="(item, i) in listItems" v-bind:key="i" class="post">
<!--포인트 영역-->
<div class="points">
{{ item.points || 0 }}
</div>
<!-- 기타 정보 영역-->
<div>
<!-- 타이블 -->
<p class="news-title">
<template v-if="item.domain">
<a v-bind:href="item.url">
{{ item.title }}
</a>
</template>
<template v-else>
<router-link v-bind:to="`item/${item.id}`">
{{ item.title }}
</router-link>
</template>
</p>
<small class="link-text">
{{ item.time_ago }}
by
<router-link v-if="item.user" v-bind:to="`/user/${item.user}`" class="link-text">
{{ item.user }}
</router-link>
<a :href="item.url" v-else>
{{ item.domain }}
</a>
</small>
</div>
</li>
</ul>
</div>
</template>
<script>
export default {
computed: {
listItems() {
return this.$store.state.list;
// const routename = this.$route.name;
// if (routename === 'news') {
// return this.$store.state.news;
// } else if (routename === 'ask') {
// return this.$store.state.asks;
// } else if (routename === 'jobs') {
// return this.$store.state.jobs;
// }
// return this.$store.state.news;
}
},
};
</script>
<style scoped>
.news-list {
margin: 0;
padding: 0;
}
.post {
list-style: none;
display: flex;
align-items: center;
border-bottom: 1px solid #eee;
}
.points {
width: 80px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
color: #42b883;
}
.news-title {
margin: 0;
}
.link-text {
color: #828282;
}
</style>
반응형
'vue.js > vue.js 2' 카테고리의 다른 글
65. UX를 고려한 데이터 호출 시점 (0) | 2022.08.07 |
---|---|
64. <vue-news> 프로젝트 | Mixins (여러 컴포넌트 간에 공통으로 사용되고 있는 로직, 기능들을 재사용하는 방법) (0) | 2022.08.07 |
62. <vue-news> 프로젝트 | list 공통 컴포넌트화 (0) | 2022.08.06 |
61. <vue-news> 프로젝트 | 1차 완성 (0) | 2022.08.06 |
60. <vue-news> 프로젝트 | Router 트렌지션 (0) | 2022.08.06 |