Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
node-sample
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
周韬
node-sample
Commits
ad310a94
Commit
ad310a94
authored
Apr 19, 2017
by
Evan You
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor: universal data prefetch function
parent
88be9dd8
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
64 additions
and
59 deletions
+64
-59
app.js
src/app.js
+1
-1
Item.vue
src/components/Item.vue
+1
-1
entry-client.js
src/entry-client.js
+14
-0
entry-server.js
src/entry-server.js
+6
-2
filters.js
src/util/filters.js
+0
-0
title.js
src/util/title.js
+1
-1
CreateListView.js
src/views/CreateListView.js
+9
-3
ItemList.vue
src/views/ItemList.vue
+0
-8
ItemView.vue
src/views/ItemView.vue
+25
-29
UserView.vue
src/views/UserView.vue
+7
-14
No files found.
src/app.js
View file @
ad310a94
...
...
@@ -3,7 +3,7 @@ import App from './App.vue'
import
{
createStore
}
from
'./store'
import
{
createRouter
}
from
'./router'
import
{
sync
}
from
'vuex-router-sync'
import
*
as
filters
from
'./filters'
import
*
as
filters
from
'./
util/
filters'
// register global utility filters.
Object
.
keys
(
filters
).
forEach
(
key
=>
{
...
...
src/components/Item.vue
View file @
ad310a94
...
...
@@ -27,7 +27,7 @@
</template>
<
script
>
import
{
timeAgo
}
from
'../filters'
import
{
timeAgo
}
from
'../
util/
filters'
export
default
{
name
:
'news-item'
,
...
...
src/entry-client.js
View file @
ad310a94
import
Vue
from
'vue'
import
'es6-promise/auto'
import
{
createApp
}
from
'./app'
// a global mixin to invoke fetchData on the client
Vue
.
mixin
({
beforeMount
()
{
const
{
fetchData
}
=
this
.
$options
if
(
fetchData
)
{
this
.
dataPromise
=
fetchData
(
this
.
$store
,
this
.
$route
.
params
)
}
}
})
const
{
app
,
router
,
store
}
=
createApp
()
// prime the store with server-initialized state.
...
...
src/entry-server.js
View file @
ad310a94
...
...
@@ -23,12 +23,16 @@ export default context => {
if
(
!
matchedComponents
.
length
)
{
reject
({
code
:
404
})
}
// Call
preFetch
hooks on components matched by the route.
// Call
fetchData
hooks on components matched by the route.
// A preFetch hook dispatches a store action and returns a Promise,
// which is resolved when the action is complete and store state has been
// updated.
Promise
.
all
(
matchedComponents
.
map
(
component
=>
{
return
component
.
preFetch
&&
component
.
preFetch
(
store
)
return
component
.
fetchData
&&
component
.
fetchData
(
store
,
router
.
currentRoute
.
params
,
context
)
})).
then
(()
=>
{
isDev
&&
console
.
log
(
`data pre-fetch:
${
Date
.
now
()
-
s
}
ms`
)
// After all preFetch hooks are resolved, our store is now
...
...
src/
filters/index
.js
→
src/
util/filters
.js
View file @
ad310a94
File moved
src/util/
set-
title.js
→
src/util/title.js
View file @
ad310a94
export
function
setTitle
(
title
,
context
)
{
export
const
setTitle
=
(
title
,
context
)
=>
{
title
=
`Vue HN 2.0 |
${
title
}
`
if
(
context
)
{
// server
...
...
src/views/CreateListView.js
View file @
ad310a94
import
ItemList
from
'./ItemList.vue'
import
{
setTitle
}
from
'../util/title'
const
camelize
=
str
=>
str
.
charAt
(
0
).
toUpperCase
()
+
str
.
slice
(
1
)
// This is a factory function for dynamically creating root-level list views,
// since they share most of the logic except for the type of items to display.
...
...
@@ -6,10 +9,13 @@ import ItemList from './ItemList.vue'
export
default
function
createListView
(
type
)
{
return
{
name
:
`
${
type
}
-stories-view`
,
// this will be called during SSR to pre-fetch data into the store!
preFetch
(
store
)
{
return
store
.
dispatch
(
'FETCH_LIST_DATA'
,
{
type
})
fetchData
(
store
,
params
,
context
)
{
return
store
.
dispatch
(
'FETCH_LIST_DATA'
,
{
type
}).
then
(()
=>
{
setTitle
(
camelize
(
type
),
context
)
})
},
render
(
h
)
{
return
h
(
ItemList
,
{
props
:
{
type
}})
}
...
...
src/views/ItemList.vue
View file @
ad310a94
...
...
@@ -21,12 +21,9 @@
<
script
>
import
{
watchList
}
from
'../api'
import
{
setTitle
}
from
'../util/set-title'
import
Item
from
'../components/Item.vue'
import
Spinner
from
'../components/Spinner.vue'
const
camelize
=
str
=>
str
.
charAt
(
0
).
toUpperCase
()
+
str
.
slice
(
1
)
export
default
{
name
:
'item-list'
,
...
...
@@ -62,12 +59,7 @@ export default {
}
},
serverRendered
(
context
)
{
setTitle
(
camelize
(
this
.
type
),
context
)
},
beforeMount
()
{
setTitle
(
camelize
(
this
.
type
))
if
(
this
.
$root
.
_isMounted
)
{
this
.
loadItems
(
this
.
page
)
}
...
...
src/views/ItemView.vue
View file @
ad310a94
...
...
@@ -28,55 +28,51 @@
</template>
<
script
>
import
{
setTitle
}
from
'../util/
set-
title'
import
{
setTitle
}
from
'../util/title'
import
Spinner
from
'../components/Spinner.vue'
import
Comment
from
'../components/Comment.vue'
function
fetchItem
(
store
)
{
return
store
.
dispatch
(
'FETCH_ITEMS'
,
{
ids
:
[
store
.
state
.
route
.
params
.
id
]
})
}
// recursively fetch all descendent comments
function
fetchComments
(
store
,
item
)
{
if
(
item
.
kids
)
{
return
store
.
dispatch
(
'FETCH_ITEMS'
,
{
ids
:
item
.
kids
}).
then
(()
=>
Promise
.
all
(
item
.
kids
.
map
(
id
=>
{
return
fetchComments
(
store
,
store
.
state
.
items
[
id
])
})))
}
}
export
default
{
name
:
'item-view'
,
components
:
{
Spinner
,
Comment
},
data
()
{
return
{
data
:
()
=>
(
{
loading
:
true
}
},
}),
computed
:
{
item
()
{
return
this
.
$store
.
state
.
items
[
this
.
$route
.
params
.
id
]
}
},
// on the server, only fetch the item itself
preFetch
:
fetchItem
,
serverRendered
(
context
)
{
setTitle
(
this
.
item
.
title
,
context
)
fetchData
(
store
,
params
,
context
)
{
return
store
.
dispatch
(
'FETCH_ITEMS'
,
{
ids
:
[
params
.
id
]
}).
then
(()
=>
{
const
item
=
store
.
state
.
items
[
params
.
id
]
setTitle
(
item
.
title
,
context
)
})
},
// on the client, fetch item + comments
// on the client, fetch all comments
beforeMount
()
{
fetchItem
(
this
.
$store
).
then
(()
=>
{
setTitle
(
this
.
item
.
title
)
this
.
dataPromise
.
then
(()
=>
{
fetchComments
(
this
.
$store
,
this
.
item
).
then
(()
=>
{
this
.
loading
=
false
})
})
}
}
// recursively fetch all descendent comments
function
fetchComments
(
store
,
item
)
{
if
(
item
.
kids
)
{
return
store
.
dispatch
(
'FETCH_ITEMS'
,
{
ids
:
item
.
kids
}).
then
(()
=>
Promise
.
all
(
item
.
kids
.
map
(
id
=>
{
return
fetchComments
(
store
,
store
.
state
.
items
[
id
])
})))
}
}
</
script
>
<
style
lang=
"stylus"
>
...
...
src/views/UserView.vue
View file @
ad310a94
...
...
@@ -17,30 +17,23 @@
</template>
<
script
>
import
{
setTitle
}
from
'../util/
set-
title'
import
{
setTitle
}
from
'../util/title'
import
Spinner
from
'../components/Spinner.vue'
function
fetchUser
(
store
)
{
return
store
.
dispatch
(
'FETCH_USER'
,
{
id
:
store
.
state
.
route
.
params
.
id
})
}
export
default
{
name
:
'user-view'
,
components
:
{
Spinner
},
computed
:
{
user
()
{
return
this
.
$store
.
state
.
users
[
this
.
$route
.
params
.
id
]
}
},
preFetch
:
fetchUser
,
serverRendered
(
context
)
{
setTitle
(
this
.
user
.
id
,
context
)
},
beforeMount
()
{
fetchUser
(
this
.
$store
).
then
(()
=>
{
setTitle
(
this
.
user
.
id
)
fetchData
(
store
,
params
,
context
)
{
return
store
.
dispatch
(
'FETCH_USER'
,
{
id
:
params
.
id
}).
then
(()
=>
{
const
user
=
store
.
state
.
users
[
params
.
id
]
setTitle
(
user
.
id
,
context
)
})
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment