Commit f519772c authored by Evan You's avatar Evan You

item view

parent e9257b85
<template>
<li class="news-item">{{ item.title }}</li>
<li class="news-item">
<a :href="item.url" target="_blank">{{ item.title }}</a><br>
<router-link :to="'/item/' + item.id">
{{ item.descendants }} comments
</router-link>
| by
<router-link :to="'/user/' + item.by">
{{ item.by }}
</router-link>
</li>
</template>
<script>
......@@ -12,4 +21,5 @@ export default {
<style lang="stylus">
.news-item
background-color #fff
margin 10px 0
</style>
......@@ -16,8 +16,8 @@
<transition :name="transition">
<div class="news-list" :key="displayedPage">
<transition-group tag="ul" name="item">
<news-item v-for="item in displayedItems" :key="item.id" :item="item">
</news-item>
<item v-for="item in displayedItems" :key="item.id" :item="item">
</item>
</transition-group>
</div>
</transition>
......@@ -26,15 +26,15 @@
<script>
import Spinner from './Spinner.vue'
import NewsItem from './NewsItem.vue'
import Item from './Item.vue'
import { watchList } from '../store/api'
export default {
name: 'NewsList',
name: 'item-list',
components: {
Spinner,
NewsItem
Item
},
props: {
......@@ -68,20 +68,20 @@ export default {
}
},
mounted () {
beforeMount () {
if (this.$root._isMounted) {
this.loadItems(this.page)
}
// watch the current list for realtime updates
this.unwatchList = watchList(this.type, ids => {
this.$store.commit('SET_LIST', { type: this.type, ids })
this.$store.dispatch('FETCH_ACTIVE_ITEMS').then(() => {
this.$store.dispatch('ENSURE_ACTIVE_ITEMS').then(() => {
this.displayedItems = this.$store.getters.activeItems
})
})
},
destroyed () {
beforeDestroy () {
this.unwatchList()
},
......@@ -94,7 +94,7 @@ export default {
methods: {
loadItems (to = this.page, from = -1) {
this.loading = true
this.$store.dispatch('FETCH_DATA_FOR_TYPE', {
this.$store.dispatch('FETCH_LIST_DATA', {
type: this.type
}).then(() => {
if (this.page < 0 || this.page > this.maxPage) {
......
......@@ -4,7 +4,9 @@ import Router from 'vue-router'
Vue.use(Router)
import { createListView } from '../views/CreateListView'
import About from '../views/About.vue'
import ItemView from '../views/ItemView.vue'
import UserView from '../views/UserView.vue'
import AboutView from '../views/AboutView.vue'
export default new Router({
mode: 'history',
......@@ -14,7 +16,9 @@ export default new Router({
{ path: '/show/:page(\\d+)?', component: createListView('show') },
{ path: '/ask/:page(\\d+)?', component: createListView('ask') },
{ path: '/job/:page(\\d+)?', component: createListView('job') },
{ path: '/about', component: About },
{ path: '/item/:id(\\d+)', component: ItemView },
{ path: '/user/:id', component: UserView },
{ path: '/about', component: AboutView },
{ path: '*', redirect: '/top/1' }
]
})
......@@ -79,14 +79,11 @@ export function watchList (type, cb) {
if (first) {
first = false
} else {
console.log(`update for ${type}`)
cb(snapshot.val())
}
}
console.log(`watching ${type}...`)
ref.on('value', handler)
return () => {
console.log(`stop watching ${type}`)
ref.off('value', handler)
}
}
import Vue from 'vue'
import Vuex from 'vuex'
import { fetchIdsByType, fetchItems } from './api'
import { fetchIdsByType, fetchItem, fetchItems } from './api'
Vue.use(Vuex)
......@@ -23,17 +23,23 @@ const store = new Vuex.Store({
actions: {
// ensure data for rendering given list type
FETCH_DATA_FOR_TYPE: ({ commit, dispatch, state, getters }, { type }) => {
FETCH_LIST_DATA: ({ commit, dispatch, state, getters }, { type }) => {
commit('SET_ACTIVE_TYPE', { type })
return fetchIdsByType(type)
.then(ids => commit('SET_LIST', { type, ids }))
.then(() => dispatch('FETCH_ACTIVE_ITEMS'))
.then(() => dispatch('ENSURE_ACTIVE_ITEMS'))
},
// ensure all active items are fetched
FETCH_ACTIVE_ITEMS: ({ commit, state, getters }) => {
ENSURE_ACTIVE_ITEMS: ({ dispatch, getters }) => {
return dispatch('FETCH_ITEMS', {
ids: getters.activeIds
})
},
FETCH_ITEMS: ({ commit, state }, { ids }) => {
// only fetch items that we don't already have.
const ids = getters.activeIds.filter(id => !state.items[id])
ids = ids.filter(id => !state.items[id])
if (ids.length) {
return fetchItems(ids).then(items => commit('SET_ITEMS', { items }))
} else {
......
......@@ -7,6 +7,6 @@
<script>
export default {
name: 'about'
name: 'about-view'
}
</script>
import NewsList from '../components/NewsList.vue'
import ItemList from '../components/ItemList.vue'
// 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 {
name: `${type}-stories`,
components: {
NewsList
},
name: `${type}-stories-view`,
// this will be called during SSR to pre-fetch data into the store!
preFetch (store) {
return store.dispatch('FETCH_DATA_FOR_TYPE', { type })
},
created () {
this.$store.commit('SET_ACTIVE_TYPE', { type })
return store.dispatch('FETCH_LIST_DATA', { type })
},
render (h) {
return h(NewsList, { props: { type }})
return h(ItemList, { props: { type }})
}
}
}
<template>
<div class="item-view">
<h2>Item!</h2>
<p v-if="item">{{ item.title }}</p>
</div>
</template>
<script>
export default {
name: 'item-view',
computed: {
item () {
return this.$store.state.items[this.$route.params.id]
}
},
beforeMount () {
this.$store.dispatch('FETCH_ITEMS', {
ids: [this.$route.params.id]
})
}
}
</script>
<template>
<div class="user-view">
<h2>User!</h2>
</div>
</template>
<script>
export default {
name: 'user-view',
preFetch (store) {
return store.dispatch('FETCH_USER', {
id: store.state.route.params.id
})
},
mounted () {
}
}
</script>
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