vue로 구현하는 예제(ver.6)입니다.
- 리팩토링 -
예제는 인프런의 캡틴판교, "장기효"님의 Vue.js 완벽 가이드 - 실습과 리팩토링으로 배우는 실전 개념을
들으면서 공부한 내용입니다.
리팩토링 컴포넌트 공통화
페이지에서 사용되는 컴포넌트들의 패턴이 중복되어 사용되었을때
이를 공통 컴포넌트화 시킴으로써 코드를 간편화, 구조화 시킵니다.
구현 내용
News/Ask/Jobs 각 페이지를
ListItem.vue에서 컴포넌트를 시킨 후
각각의 페이지에서 ListItem.vue를 import 시킵니다.
리팩토링 before
vue > NewsView.vue
<template>
<div>
<ul class="new-list">
<li class="post" v-for="item in askItems" v-bind:key="item.id">
<div class="points">{{ item.points }}</div>
<div>
<div class="new-title">
<a v-bind:href="item.url" target="_blank">{{
item.title
}}</a>
</div>
<small class="link-text"
>{{ item.time_ago }} by
<router-link class="link-text" v-bind:to="`/user/${item.user}`">{{
item.user
}}</router-link></small
>
</div>
</li>
</ul>
</div>
</template>
<script>
export default {
created() {
this.$store.dispatch("FETCH_NEWS");
},
};
</script>
<style>
.new-list {
margin: 0;
padding: 0;
}
.post {
list-style: none;
display: flex !important;
align-items: center;
border-bottom: 1px solid #eee;
}
.points {
width: 80px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
color: #42b883;
}
.new-title {
margin: 0;
}
.link-text {
color: #828282;
}
</style>
리팩토링 after
· vue > ListItem.vue 파일 생성하여 NewsView.vue의 전체 코드를 copy
· 각 컴포넌트에서 다른 부분은 분기처리(created, template)
· 각 컴포넌트에서는 ListItem.vue를 import
created() before
각 컴포넌트
//ListView.vue
export default {
created() {
this.$store.dispatch("FETCH_NEWS");
},
};
//AskView.vue
export default {
created() {
this.$store.dispatch("FETCH_ASK");
},
};
//JobsView.vue
export default {
created() {
this.$store.dispatch("FETCH_JOBS");
},
};
created() after
각 this.$store.dispatch("FETCH_XXX"); 를 this.$router에 있는것으로 분기처리를 합니다.
routes에서 각 컴포넌트별로 name 지정(this.$route.name으로 불러올수 있음)
routes > index.js
routes: [
{ path: '/news', name: 'news', component: NewsView },
{ path: '/ask', name: 'ask', component: AskView },
{ path: '/jobs', name: 'jobs', component: JobsView },
]
components > ListItem.vue
<script>
export default {
name: "list-item",
created() {
//this.$store.dispatch("FETCH_NEWS");
//this.$router에 있는것으로 분기처리 함
//console.log(this.$route);
const name = this.$route.name;
if (name === "news") {
return this.$store.dispatch("FETCH_NEWS");
} else if (name === "ask") {
return this.$store.dispatch("FETCH_ASK");
} else if (name === "jobs") {
return this.$store.dispatch("FETCH_JOBS");
}
}
};
</script>
<template> before
//NewsView.vue
<ul class="new-list">
<li class="post" v-for="item in this.$store.state.news"" v-bind:key="item.id">
<div class="points">{{ item.points }}</div>
<div>
<div class="new-title">
<a v-bind:href="item.url" target="_blank">{{
item.title
}}</a>
</div>
<small class="link-text"
>{{ item.time_ago }} by
<router-link class="link-text" v-bind:to="`/user/${item.user}`">{{
item.user
}}</router-link></small
>
</div>
</li>
</ul>
//AskView.vue
<ul class="new-list">
<li class="post" v-for="item in this.$store.state.news" v-bind:key="item.id">
<div class="points">{{ item.points }}</div>
<div>
<div class="new-title">
<router-link v-bind:to="`item/${item.id}`" target="_blank">{{
item.title
}}</router-link>
</div>
<small class="link-text"
>{{ item.time_ago }} by
<router-link class="link-text" v-bind:to="`/user/${item.user}`">{{
item.user
}}</router-link></small
>
</div>
</li>
</ul>
//JobsView.vue
<ul class="new-list">
<li
class="post"
v-for="item in this.$store.state.jobs"
v-bind:key="item.id"
>
<div class="points">{{ item.type }}</div>
<div>
<div class="new-title">
<a v-bind:href="item.url" target="_blank">{{ item.title }}</a>
</div>
<small class="link-text"
>{{ item.time_ago }} by <a :href="item.url" target="_blank">{{ item.domain }}</a>
</small
>
</div>
</li>
</ul>
<template> after
NewsView.vue
<template>
<div>
<list-item />
</div>
</template>
ListItem의 <template>, computed after
기존의 this.$store.state.news / this.$store.state.ask /this.$store.state.jobs를
listItems 하나로 정의 한 후,
computed 속성으로 this.$route.name을 이용하여 분기처리
· this.$store.state.news -> listItems 변경
· computed에 listItems 속성 추가
· this.$route.name을 이용하여 분기 처리
· v-if/v-else를 이용하여 분기 처리
components > ListItem.vue <template>
<template>
<div>
<ul class="new-list">
//기존의 this.$store.state.news(ask/jobs)를 listItems로 정의
<li class="post" v-for="item in listItems" v-bind:key="item.id">
<div class="points">{{ item.points || item.type }}</div>
<div>
<div class="new-title">
<a v-bind:href="item.url" target="_blank" v-if="item.domain">{{
item.title
}}</a>
<router-link
v-else=""
v-bind:to="`item/${item.id}`"
target="_blank"
>{{ item.title }}</router-link
>
</div>
<small class="link-text"
>{{ item.time_ago }} by
<router-link
class="link-text"
v-bind:to="`/user/${item.user}`"
v-if="item.user"
>{{ item.user }}</router-link
>
<a :href="item.url" target="_blank" v-else>{{ item.domain }}</a>
</small>
</div>
</li>
</ul>
</div>
</template>
components > ListItem.vue <script>
computed: {
listItems() {
const name = this.$route.name;
if (name === "news") {
return this.$store.state.news;
} else if (name === "ask") {
return this.$store.state.ask;
} else if (name === "jobs") {
return this.$store.state.jobs;
}
},
},
'개발 > React' 카테고리의 다른 글
[vue] vue.js props / emit 사용방법 (0) | 2021.02.03 |
---|---|
[vue] vue.js 리팩토링: 공통 컴포넌트화(api 통해 뉴스 사이트 구현 ver.7) (0) | 2021.02.01 |
[vue] vue getters, v-html, transition(api 통해 뉴스 사이트 구현 ver.5) (0) | 2021.01.21 |
[vue] vue.js vue 동적 라우트(api 통해 뉴스 사이트 구현 ver.4) (0) | 2021.01.18 |
[vue] vue vuex , store적용(api 통해 뉴스 사이트 구현 ver.3) (0) | 2021.01.14 |
댓글