Commit 74736699 authored by Evan You's avatar Evan You

mutiple lists

parent 144379b7
...@@ -25,7 +25,7 @@ body ...@@ -25,7 +25,7 @@ body
width 30px width 30px
.view .view
transition all .35s ease transition all .2s ease
.view-enter, .view-leave-active .view-enter, .view-leave-active
opacity 0 opacity 0
......
...@@ -44,50 +44,46 @@ export default { ...@@ -44,50 +44,46 @@ export default {
data () { data () {
return { return {
loading: false, loading: false,
displayedPage: -1, transition: 'slide-left',
displayedItems: [], displayedPage: Number(this.$store.state.route.params.page) || 1,
transition: 'slide-left' displayedItems: this.$store.getters.activeItems
} }
}, },
computed: { computed: {
activeItems () {
return this.$store.getters.activeItems
},
page () { page () {
return Number(this.$store.state.route.params.page) || 1 return Number(this.$store.state.route.params.page) || 1
}, },
maxPage () { maxPage () {
const { itemsPerPage, itemIdsByType } = this.$store.state const { itemsPerPage, lists } = this.$store.state
return Math.floor(itemIdsByType[this.type].length / itemsPerPage) return Math.ceil(lists[this.type].length / itemsPerPage)
}, },
hasMore () { hasMore () {
return this.page < this.maxPage return this.page < this.maxPage
} }
}, },
created () {
this.displayedPage = this.page
this.displayedItems = this.activeItems
},
mounted () { mounted () {
if (this.page > this.maxPage || this.page < 1) { this.loadItems(this.page, -1)
this.$router.replace(`/${this.type}/1`)
} else {
fetchInitialData(this.type).then(() => {
this.displayedItems = this.activeItems
})
}
}, },
watch: { watch: {
page (to, from) { page (to, from) {
this.loadItems(to, from)
}
},
methods: {
loadItems (to, from) {
this.loading = true this.loading = true
this.$store.dispatch('FETCH_ACTIVE_ITEMS').then(() => { fetchInitialData(this.type).then(() => {
if (this.page < 0 || this.page > this.maxPage) {
this.$router.replace(`/${this.type}/1`)
return
}
this.transition = to > from ? 'slide-left' : 'slide-right' this.transition = to > from ? 'slide-left' : 'slide-right'
this.displayedPage = to this.displayedPage = to
this.displayedItems = this.activeItems this.displayedItems = this.$store.getters.activeItems
this.loading = false this.loading = false
}) })
} }
......
...@@ -3,17 +3,17 @@ import Router from 'vue-router' ...@@ -3,17 +3,17 @@ import Router from 'vue-router'
Vue.use(Router) Vue.use(Router)
import { createStoriesView } from '../views/CreateStoriesView' import { createListView } from '../views/CreateListView'
import About from '../views/About.vue' import About from '../views/About.vue'
export default new Router({ export default new Router({
mode: 'history', mode: 'history',
routes: [ routes: [
{ path: '/top/:page(\\d+)?', component: createStoriesView('top') }, { path: '/top/:page(\\d+)?', component: createListView('top') },
{ path: '/new/:page(\\d+)?', component: createStoriesView('new') }, { path: '/new/:page(\\d+)?', component: createListView('new') },
{ path: '/show/:page(\\d+)?', component: createStoriesView('show') }, { path: '/show/:page(\\d+)?', component: createListView('show') },
{ path: '/ask/:page(\\d+)?', component: createStoriesView('ask') }, { path: '/ask/:page(\\d+)?', component: createListView('ask') },
{ path: '/job/:page(\\d+)?', component: createStoriesView('job') }, { path: '/job/:page(\\d+)?', component: createListView('job') },
{ path: '/about', component: About }, { path: '/about', component: About },
{ path: '*', redirect: '/top/1' } { path: '*', redirect: '/top/1' }
] ]
......
...@@ -8,13 +8,11 @@ const store = new Vuex.Store({ ...@@ -8,13 +8,11 @@ const store = new Vuex.Store({
state: { state: {
activeType: null, activeType: null,
itemsPerPage: 20, itemsPerPage: 20,
// the current items being displayed
activeItemIds: [/* number */],
// fetched items by id. This also serves as a cache to some extent // fetched items by id. This also serves as a cache to some extent
items: {/* [id: number]: Item */}, items: {/* [id: number]: Item */},
// the id lists for each type of stories // the id lists for each type of stories
// will be periodically updated in realtime // will be periodically updated in realtime
itemIdsByType: { lists: {
top: [], top: [],
new: [], new: [],
show: [], show: [],
...@@ -42,7 +40,7 @@ const store = new Vuex.Store({ ...@@ -42,7 +40,7 @@ const store = new Vuex.Store({
state.activeType = type state.activeType = type
}, },
SET_IDS: (state, { type, ids }) => { SET_IDS: (state, { type, ids }) => {
state.itemIdsByType[type] = ids state.lists[type] = ids
}, },
SET_ITEMS: (state, { items }) => { SET_ITEMS: (state, { items }) => {
items.forEach(item => { items.forEach(item => {
...@@ -53,12 +51,12 @@ const store = new Vuex.Store({ ...@@ -53,12 +51,12 @@ const store = new Vuex.Store({
getters: { getters: {
activeIds (state) { activeIds (state) {
const { activeType, itemsPerPage, itemIdsByType } = state const { activeType, itemsPerPage, lists } = state
const page = Number(state.route.params.page) || 1 const page = Number(state.route.params.page) || 1
if (activeType) { if (activeType) {
const start = (page - 1) * itemsPerPage const start = (page - 1) * itemsPerPage
const end = page * itemsPerPage const end = page * itemsPerPage
return itemIdsByType[activeType].slice(start, end) return lists[activeType].slice(start, end)
} else { } else {
return [] return []
} }
......
import NewsList from '../components/NewsList.vue' import NewsList from '../components/NewsList.vue'
import { fetchInitialData } from '../store' import { fetchInitialData } from '../store'
export function createStoriesView (type) { // factory function for creating root-level list views
// since they share most of the logic except for the type of items to display.
export function createListView (type) {
return { return {
name: `${type}-stories`, name: `${type}-stories`,
components: { components: {
NewsList NewsList
}, },
prefetch () { prefetch () {
fetchInitialData(type) return fetchInitialData(type)
},
created () {
this.$store.commit('SET_ACTIVE_TYPE', { type })
}, },
render (h) { render (h) {
return h(NewsList, { props: { type }}) return h(NewsList, { props: { type }})
......
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