Commit 61d8c288 authored by Evan You's avatar Evan You

refactor store naming + use stylus

parent c2559459
......@@ -31,6 +31,8 @@
"css-loader": "^0.23.1",
"extract-text-webpack-plugin": "^2.0.0-beta.3",
"file-loader": "^0.8.4",
"stylus": "^0.54.5",
"stylus-loader": "^2.1.2",
"vue-loader": "^9.2.2",
"webpack": "^2.1.0-beta.20",
"webpack-dev-middleware": "^1.6.1",
......
......@@ -13,23 +13,22 @@
</div>
</template>
<style>
body {
font-family: Roboto, Helvetica, sans-serif;
}
.logo {
width: 30px;
}
.view {
transition: all .35s ease;
}
.view-enter, .view-leave-active {
opacity: 0;
}
a {
color: #4fc08d;
}
a.disabled {
color: #999;
}
<style lang="stylus">
body
font-family Roboto, Helvetica, sans-serif
.logo
width 30px
.view
transition all .35s ease
.view-enter, .view-leave-active
opacity 0
a
color #4fc08d
a.disabled
color #999
</style>
......@@ -10,41 +10,40 @@ export default {
}
</script>
<style>
.spinner {
opacity: 0;
transition: opacity .3s ease;
animation: rotator 1.4s linear infinite;
animation-play-state: paused;
}
<style lang="stylus">
$offset = 126
$duration = 1.4s
.spinner.show {
opacity: 1;
animation-play-state: running;
}
.spinner
opacity 0
transition opacity .15s ease
animation rotator $duration linear infinite
animation-play-state paused
@keyframes rotator {
0% { transform: scale(0.5) rotate(0deg); }
100% { transform: scale(0.5) rotate(270deg); }
}
.spinner.show
opacity 1
animation-play-state running
.spinner .path {
stroke: #4fc08d;
stroke-dasharray: 126;
stroke-dashoffset: 0;
transform-origin: center;
animation: dash 1.4s ease-in-out infinite;
}
@keyframes rotator
0%
transform scale(0.5) rotate(0deg)
100%
transform scale(0.5) rotate(270deg)
@keyframes dash {
0% { stroke-dashoffset: 126; }
50% {
stroke-dashoffset: 32;
transform:rotate(135deg);
}
100% {
stroke-dashoffset: 126;
transform:rotate(450deg);
}
}
.spinner .path
stroke #4fc08d
stroke-dasharray $offset
stroke-dashoffset 0
transform-origin center
animation dash 1.4s ease-in-out infinite
@keyframes dash
0%
stroke-dashoffset $offset
50%
stroke-dashoffset ($offset/2)
transform rotate(135deg)
100%
stroke-dashoffset $offset
transform rotate(450deg)
</style>
......@@ -6,30 +6,30 @@ Vue.use(Vuex)
const store = new Vuex.Store({
state: {
storiesPerPage: 20,
topStoryIds: [],
itemsPerPage: 20,
activeItemIds: [],
items: {}
},
actions: {
FETCH_TOP_IDS: ({ commit }) => {
FETCH_IDS: ({ commit }) => {
return fetchTopIds().then(ids => {
commit('RECEIVE_TOP_IDS', { ids })
commit('SET_ACTIVE_IDS', { ids })
})
},
FETCH_NEWS: ({ commit, state }) => {
FETCH_DISPLAYED_ITEMS: ({ commit, state }) => {
const ids = getDisplayedIds(state)
return fetchItems(ids).then(items => {
commit('RECEIVE_ITEMS', { items })
commit('SET_ITEMS', { items })
})
}
},
mutations: {
RECEIVE_TOP_IDS: (state, { ids }) => {
state.topStoryIds = ids
SET_ACTIVE_IDS: (state, { ids }) => {
state.activeItemIds = ids
},
RECEIVE_ITEMS: (state, { items }) => {
SET_ITEMS: (state, { items }) => {
items.forEach(item => {
Vue.set(state.items, item.id, item)
})
......@@ -37,7 +37,7 @@ const store = new Vuex.Store({
},
getters: {
news: state => {
displayedItems: state => {
const ids = getDisplayedIds(state)
return ids.map(id => state.items[id]).filter(_ => _)
}
......@@ -47,17 +47,17 @@ const store = new Vuex.Store({
// watch for realtime top IDs updates on the client
if (typeof window !== 'undefined') {
watchTopIds(ids => {
store.commit('RECEIVE_TOP_IDS', { ids })
store.dispatch('FETCH_NEWS')
store.commit('SET_ACTIVE_IDS', { ids })
store.dispatch('FETCH_DISPLAYED_ITEMS')
})
}
function getDisplayedIds (state) {
const page = Number(state.route.params.page) || 1
const { storiesPerPage, topStoryIds } = state
const start = (page - 1) * storiesPerPage
const end = page * storiesPerPage
return topStoryIds.slice(start, end)
const { itemsPerPage, activeItemIds } = state
const start = (page - 1) * itemsPerPage
const end = page * itemsPerPage
return activeItemIds.slice(start, end)
}
export default store
<template>
<div>
<h2>News <spinner :show="loading"></spinner></h2>
<spinner :show="loading"></spinner>
<ul>
<li>
<router-link v-if="page > 1" :to="'/news/' + (page - 1)">prev</router-link>
......@@ -28,8 +28,8 @@ import NewsItem from '../components/NewsItem.vue'
const fetchInitialData = store => {
return store
.dispatch(`FETCH_TOP_IDS`)
.then(() => store.dispatch(`FETCH_NEWS`))
.dispatch(`FETCH_IDS`)
.then(() => store.dispatch(`FETCH_DISPLAYED_ITEMS`))
}
export default {
......@@ -43,7 +43,7 @@ export default {
return {
loading: false,
displayPage: this.$route.params.page,
displayItems: this.$store.getters.news,
displayItems: this.$store.getters.displayedItems,
transition: 'slide-left'
}
},
......@@ -52,8 +52,8 @@ export default {
return Number(this.$route.params.page)
},
maxPage () {
const { storiesPerPage, topStoryIds } = this.$store.state
return Math.floor(topStoryIds.length / storiesPerPage)
const { itemsPerPage, activeItemIds } = this.$store.state
return Math.floor(activeItemIds.length / itemsPerPage)
},
hasMore () {
return this.page < this.maxPage
......@@ -68,12 +68,12 @@ export default {
watch: {
'$route' (to, from) {
this.loading = true
this.$store.dispatch(`FETCH_NEWS`).then(() => {
this.$store.dispatch(`FETCH_DISPLAYED_ITEMS`).then(() => {
const toPage = Number(to.params.page)
const fromPage = Number(from.params.page)
this.transition = toPage > fromPage ? 'slide-left' : 'slide-right'
this.displayPage = toPage
this.displayItems = this.$store.getters.news.slice()
this.displayItems = this.$store.getters.displayedItems
this.loading = false
})
}
......@@ -81,29 +81,28 @@ export default {
}
</script>
<style>
.news-list {
position: absolute;
transition: all .5s cubic-bezier(.55,0,.1,1);
}
.slide-left-enter, .slide-right-leave-active {
opacity: 0;
transform: translate(30px, 0);
}
.slide-left-leave-active, .slide-right-enter {
opacity: 0;
transform: translate(-30px, 0);
}
.item-move, .item-enter-active, .item-leave-active {
transition: all .5s cubic-bezier(.55,0,.1,1);
}
.item-enter {
opacity: 0;
transform: translate(30px, 0);
}
.item-leave-active {
position: absolute;
opacity: 0;
transform: translate(30px, 0);
}
<style lang="stylus">
.news-list
position absolute
transition all .5s cubic-bezier(.55,0,.1,1)
.slide-left-enter, .slide-right-leave-active
opacity 0
transform translate(30px, 0)
.slide-left-leave-active, .slide-right-enter
opacity 0
transform translate(-30px, 0)
.item-move, .item-enter-active, .item-leave-active
transition all .5s cubic-bezier(.55,0,.1,1)
.item-enter
opacity 0
transform translate(30px, 0)
.item-leave-active
position absolute
opacity 0
transform translate(30px, 0)
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment