안녕하세요. @anpigon입니다.
이 포스팅은 제가 스팀잇과 프론트엔드 기술을 공부하고 앱을 구현하는 과정을 정리한 글입니다. 그래서 설명이 많이 부족할 수 있습니다. 궁금한 사항은 댓글로 문의하시면, 최대한 답변해드리도록 노력하겠습니다.
이번에는 아래와 같이 보팅 내역을 볼 수 있는 페이지를 구현하였습니다.
구현된 앱은 steemlog.github.io 에서 확인 할 수 있습니다.
VoteHistory 컴포넌트 구현하기
보팅 내역을 표시하는 VoteHistory 컴포넌트 를 구현하자. 아래와 같이 VoteHistory.vue 파일을 생성한다.
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 export default { computed : { votes () { let totalRshares = 0 let totalWeight = 0 this .active_votes.forEach(e => { totalRshares += parseFloat (e.rshares) totalWeight += parseFloat (e.weight) }) return this .active_votes.map(e => { let value, curation if (this .pending_payout_value > 0 ) { value = (e.rshares * (this .global.rewardBalance / this .global.recentClaims) * this .global.price) curation = '≈$' + (e.weight / this .total_vote_weight * this .pending_payout_value * 0.25 / this .global.price).toFixed(3 ) } else { const o = '$' + this .total_payout_value / (this .total_payout_value + this .curator_payout_value) value = e.rshares / totalRshares * parseFloat (this .total_payout_value / o) curation = (e.weight / totalWeight * this .curator_payout_value).toFixed(3 ) } return { voter : e.voter, reputation : steem.formatter.reputation(e.reputation), weight : e.percent / 100 , value : value.toFixed(3 ), curation : curation, time : new Date (e.time + 'Z' ) } }) }, ...mapState({ global : state => state.global }) }, beforeCreate () { const author = this .$route.params.author const permlink = this .$route.params.permlink steem.api.getContentAsync(author, permlink) .then(n => { this .title = n.title this .total_vote_weight = n.total_vote_weight this .pending_payout_value = parseFloat (n.pending_payout_value.split(' ' )[0 ]) this .total_payout_value = parseFloat (n.total_payout_value.split(' ' )[0 ]) this .curator_payout_value = parseFloat (n.curator_payout_value.split(' ' )[0 ]) this .active_votes = n.active_votes this .author = n.author this .author_reputation = n.author_reputation this .created = n.created this .category = n.category this .net_votes = n.net_votes this .children = n.children this .cashout_time = n.cashout_time }) .catch(e => console .log(e)) .finally(() => (this .loading = false )) }, created () { this .$store.dispatch('global/loadGlobalProperties' ) } }
코드량이 많아서 핵심 로직만 남기고 생략하였습니다. 전체 소스는 깃허브 소스를 참고하길 바랍니다.
그리고 Router에 VoteHistory 컴포넌트 경로를 추가한다. /@anpigon/steemit-7/vote
형태의 경로(path)는 VoteHistory 컴포넌트 로 연결될 것이다.
1 2 3 4 5 6 7 8 9 10 11 export default new Router({ routes : [ { path : '/@:author/:permlink/vote' , name : 'VoteHistory' , component : () => import ('@/components/VoteHistory' ) }, ] })
VoteHistory 컴포넌트 링크 연결하기
포스트 하단의 좋아요 텍스트를 클릭하면 보팅 내역 페이지로 이동하게 만들자. VoteHistory 컴포넌트 의 링크 연결에는 <router-link>
를 사용한다. Main 컴포넌트 와 PostView 컴포넌트 에서 ‘좋아요’ 텍스트를 찾아서 아래와 같이 수정한다. 이제 **‘좋아요’**를 클릭하면 보팅 내역 페이지로 이동할 것이다.
1 <router-link :to ="'/@' + author + '/' + permlink + '/vote'" class ='mr-1' > 좋아요 {{ net_votes }}명</router-link >
추가 수정사항
다음은 VoteHistory 컴포넌트 를 구현하면서 추가로 수정한 내용이다.
뒤로가기 버튼이 있는 상단바 구현하기
메인 컴포넌트 외에는 상단바에 뒤로가기 버튼만 보이도록 수정하였다.

다음과 같이 Main 라우터에 메타(meta) 데이터를 추가한다. meta.main
의 값으로 메인 컴포넌트인지 아닌지를 판단할 것이다.
1 2 3 4 5 6 7 8 9 10 11 export default new Router({ routes : [ { path : '/' , name : 'Main' , component : Main, meta : { main: true } }, ] })
그 다음에 App.vue 파일을 수정한다. computed
에 메인 컴포넌트를 판단하는 isMainComponent
를 추가하였다.
1 2 3 4 5 6 7 8 9 10 export default { computed : { isMainComponent () { return !!this .$route.meta.main } } }
그리고 아래와 같이 뒤로가기 버튼만 있는 상단바 <v-toolbar>
를 추가한다. 해당 상단바는 isMainComponent
가 false 인 경우에만 보여진다.
1 2 3 4 5 6 <v-toolbar fixed app v-show ='!isMainComponent' > <v-toolbar-side-icon @click.stop ="$router.go(-1)" > <v-icon > arrow_back_ios</v-icon > </v-toolbar-side-icon > <v-toolbar-title class ="ml-0" > 뒤로가기</v-toolbar-title > </v-toolbar >
피드, 최신글, 인기글, 대세글 메뉴 추가
아래 화면과 같이 피드, 최근글, 인기글, 대세글 메뉴를 상단바에 추가하였다.
각 메뉴를 선택했을 때 보여줄 컴포넌트를 구현하자. 우선 Main.vue 에서 글목록을 보여주는 코드를 분리하여 Discussions.vue 파일을 만들자. 피드(FeedPanel) , 최신글(CreatedPanel) , 인기글(HotPanel) , 대세글(TrendingPanel) 컴포넌트는 Discussions.vue 를 상속받아서 구현할 것이다.
생성할 컴포넌트 파일 구조는 다음과 같다.
1 2 3 4 5 6 7 8 9 10 src └── components ├── panels │ ├── Discussions . vue # 상속받을 구현체 │ ├── FeedPanel . vue # 피드 │ ├── CreatedPanel . vue # 최신글 │ ├── HotPanel . vue # 인기글 │ └── TrendingPanel . vue # 대세글 └── ...
Main.vue 에서 글목록을 담당하는 코드를 분리하여 Discussions.vue 파일에 저장한다. Main.vue 에서 분리되어 필요없는 코드를 지우고 아래와 같이 <router-view>
로 대체한다. <router-view>
영역에는 피드, 최신글, 인기글, 대세글 컴포넌트를 렌더링하여 보여줄 것이다.
1 2 3 4 5 <v-flex xs12 md9 > <keep-alive > <router-view > </router-view > </keep-alive > </v-flex >
그 다음에 FeedPanel.vue , CreatedPanel.vue , HotPanel.vue , TrendingPanel.vue 파일을 생성한다. 각각 컴포넌트들은 Discussions.vue 를 상속받아서 구현한다.
컴포넌트 상속을 구현하기 위해서 Vue에서 제공하는 기능인 믹스인(mixin) 을 사용하였다. 그리고 Discussions.vue 를 상속받아 구현된 FeedPanel.vue 의 전체 코드는 아래와 같다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <script> import steem from 'steem' import Discussions from './Discussions' export default { name : 'Feed' , mixins : [ Discussions ], methods : { getDiscussions () { const query = { tag : this .$route.params.username, limit : 11 , start_permlink : this .next.permlink, start_author : this .next.author } return steem.api.getDiscussionsByFeedAsync(query) } } } </script>
FeedPanel.vue 는 Discussions.vue 를 상속받았으므로 Discussions.vue 의 기능을 그대로 사용할 수 있다. 그래서 글을 가져오는 로직이 달라져야 하는 getDiscussions()
함수만 재정의 하였다.
CreatedPanel.vue, HotPanel.vue, TrendingPanel.vue 도 Discussions.vue 를 상속받아 구현한다.
마지막으로 Main 라우터 를 수정한다. 각 컴포넌트들은 Main.vue 하위에 있어야 한다. 그래서 아래와 같이 Main 라우터 children
에 Feed , Created , Hot , Trending 라우터를 등록하였다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 export default new Router({ routes : [ { path : '/' , name : 'Main' , component : Main, children : [ { path: 'default' , redirect : { name: 'Created' }, alias : '' }, { name: 'Feed' , path : '@:username/feed' , component : () => import ('@/components/panels/FeedPanel' ), meta : { main: true }, props : true }, { name: 'Created' , path : 'created' , component : () => import ('@/components/panels/CreatedPanel' ), meta : { main: true } }, { name: 'Hot' , path : 'hot' , component : () => import ('@/components/panels/HotPanel' ), meta : { main: true } }, { name: 'Trending' , path : 'trending' , component : () => import ('@/components/panels/TrendingPanel' ), meta : { main: true } } ] }, ] })
다음은 완성된 화면입니다.
아래 화면과 같이 메뉴를 클릭하면 피드, 최신글, 인기글, 대세글을 가져옵니다.
전체 소스 내용은 github 에서 볼 수 있습니다. 그리고 구현된 앱은 steemlog.github.io 에서 확인 할 수 있습니다.
여기까지 읽어주셔서 감사합니다.
이전글