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
6c9dd49a
Commit
6c9dd49a
authored
Apr 25, 2017
by
Evan You
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
more elegant title handling
parent
3e603e88
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
60 additions
and
28 deletions
+60
-28
server.js
server.js
+5
-1
app.js
src/app.js
+7
-2
entry-server.js
src/entry-server.js
+2
-3
title.js
src/util/title.js
+28
-8
CreateListView.js
src/views/CreateListView.js
+4
-4
ItemView.vue
src/views/ItemView.vue
+6
-5
UserView.vue
src/views/UserView.vue
+8
-5
No files found.
server.js
View file @
6c9dd49a
...
@@ -106,7 +106,11 @@ function render (req, res) {
...
@@ -106,7 +106,11 @@ function render (req, res) {
}
}
}
}
renderer
.
renderToString
({
url
:
req
.
url
},
(
err
,
html
)
=>
{
const
context
=
{
title
:
'Vue HN 2.0'
,
// default title
url
:
req
.
url
}
renderer
.
renderToString
(
context
,
(
err
,
html
)
=>
{
if
(
err
)
{
if
(
err
)
{
return
handleError
(
err
)
return
handleError
(
err
)
}
}
...
...
src/app.js
View file @
6c9dd49a
...
@@ -3,8 +3,12 @@ import App from './App.vue'
...
@@ -3,8 +3,12 @@ import App from './App.vue'
import
{
createStore
}
from
'./store'
import
{
createStore
}
from
'./store'
import
{
createRouter
}
from
'./router'
import
{
createRouter
}
from
'./router'
import
{
sync
}
from
'vuex-router-sync'
import
{
sync
}
from
'vuex-router-sync'
import
titleMixin
from
'./util/title'
import
*
as
filters
from
'./util/filters'
import
*
as
filters
from
'./util/filters'
// mixin for handling title
Vue
.
mixin
(
titleMixin
)
// register global utility filters.
// register global utility filters.
Object
.
keys
(
filters
).
forEach
(
key
=>
{
Object
.
keys
(
filters
).
forEach
(
key
=>
{
Vue
.
filter
(
key
,
filters
[
key
])
Vue
.
filter
(
key
,
filters
[
key
])
...
@@ -12,7 +16,7 @@ Object.keys(filters).forEach(key => {
...
@@ -12,7 +16,7 @@ Object.keys(filters).forEach(key => {
// Expose a factory function that creates a fresh set of store, router,
// Expose a factory function that creates a fresh set of store, router,
// app instances on each call (which is called for each SSR request)
// app instances on each call (which is called for each SSR request)
export
function
createApp
()
{
export
function
createApp
(
ssrContext
)
{
// create store and router instances
// create store and router instances
const
store
=
createStore
()
const
store
=
createStore
()
const
router
=
createRouter
()
const
router
=
createRouter
()
...
@@ -22,11 +26,12 @@ export function createApp () {
...
@@ -22,11 +26,12 @@ export function createApp () {
sync
(
store
,
router
)
sync
(
store
,
router
)
// create the app instance.
// create the app instance.
// here we inject the router
and store
to all child components,
// here we inject the router
, store and ssr context
to all child components,
// making them available everywhere as `this.$router` and `this.$store`.
// making them available everywhere as `this.$router` and `this.$store`.
const
app
=
new
Vue
({
const
app
=
new
Vue
({
router
,
router
,
store
,
store
,
ssrContext
,
render
:
h
=>
h
(
App
)
render
:
h
=>
h
(
App
)
})
})
...
...
src/entry-server.js
View file @
6c9dd49a
...
@@ -10,7 +10,7 @@ const isDev = process.env.NODE_ENV !== 'production'
...
@@ -10,7 +10,7 @@ const isDev = process.env.NODE_ENV !== 'production'
export
default
context
=>
{
export
default
context
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
const
s
=
isDev
&&
Date
.
now
()
const
s
=
isDev
&&
Date
.
now
()
const
{
app
,
router
,
store
}
=
createApp
()
const
{
app
,
router
,
store
}
=
createApp
(
context
)
// set router's location
// set router's location
router
.
push
(
context
.
url
)
router
.
push
(
context
.
url
)
...
@@ -29,8 +29,7 @@ export default context => {
...
@@ -29,8 +29,7 @@ export default context => {
Promise
.
all
(
matchedComponents
.
map
(
component
=>
{
Promise
.
all
(
matchedComponents
.
map
(
component
=>
{
return
component
.
asyncData
&&
component
.
asyncData
({
return
component
.
asyncData
&&
component
.
asyncData
({
store
,
store
,
route
:
router
.
currentRoute
,
route
:
router
.
currentRoute
ssrContext
:
context
})
})
})).
then
(()
=>
{
})).
then
(()
=>
{
isDev
&&
console
.
log
(
`data pre-fetch:
${
Date
.
now
()
-
s
}
ms`
)
isDev
&&
console
.
log
(
`data pre-fetch:
${
Date
.
now
()
-
s
}
ms`
)
...
...
src/util/title.js
View file @
6c9dd49a
export
const
setTitle
=
(
title
,
context
)
=>
{
function
getTitle
(
vm
)
{
title
=
`Vue HN 2.0 |
${
title
}
`
const
{
title
}
=
vm
.
$options
if
(
context
)
{
if
(
title
)
{
// server
return
typeof
title
===
'function'
context
.
title
=
title
?
title
.
call
(
vm
)
}
else
{
:
title
// client
document
.
title
=
title
}
}
}
}
const
serverTitleMixin
=
{
created
()
{
const
title
=
getTitle
(
this
)
if
(
title
)
{
this
.
$root
.
$options
.
ssrContext
.
title
=
`Vue HN 2.0 |
${
title
}
`
}
}
}
const
clientTitleMixin
=
{
mounted
()
{
const
title
=
getTitle
(
this
)
if
(
title
)
{
document
.
title
=
`Vue HN 2.0 |
${
title
}
`
}
}
}
export
default
process
.
env
.
VUE_ENV
===
'server'
?
serverTitleMixin
:
clientTitleMixin
src/views/CreateListView.js
View file @
6c9dd49a
...
@@ -10,12 +10,12 @@ export default function createListView (type) {
...
@@ -10,12 +10,12 @@ export default function createListView (type) {
return
{
return
{
name
:
`
${
type
}
-stories-view`
,
name
:
`
${
type
}
-stories-view`
,
asyncData
({
store
,
ssrContext
})
{
asyncData
({
store
})
{
return
store
.
dispatch
(
'FETCH_LIST_DATA'
,
{
type
}).
then
(()
=>
{
return
store
.
dispatch
(
'FETCH_LIST_DATA'
,
{
type
})
setTitle
(
camelize
(
type
),
ssrContext
)
})
},
},
title
:
camelize
(
type
),
render
(
h
)
{
render
(
h
)
{
return
h
(
ItemList
,
{
props
:
{
type
}})
return
h
(
ItemList
,
{
props
:
{
type
}})
}
}
...
...
src/views/ItemView.vue
View file @
6c9dd49a
...
@@ -49,11 +49,12 @@ export default {
...
@@ -49,11 +49,12 @@ export default {
// We only fetch the item itself before entering the view, because
// We only fetch the item itself before entering the view, because
// it might take a long time to load threads with hundreds of comments
// it might take a long time to load threads with hundreds of comments
// due to how the HN Firebase API works.
// due to how the HN Firebase API works.
asyncData
({
store
,
route
:
{
params
:
{
id
}},
ssrContext
})
{
asyncData
({
store
,
route
:
{
params
:
{
id
}}})
{
return
store
.
dispatch
(
'FETCH_ITEMS'
,
{
ids
:
[
id
]
}).
then
(()
=>
{
return
store
.
dispatch
(
'FETCH_ITEMS'
,
{
ids
:
[
id
]
})
const
item
=
store
.
state
.
items
[
id
]
},
setTitle
(
item
.
title
,
ssrContext
)
})
title
()
{
return
this
.
item
.
title
},
},
// Fetch comments when mounted on the client
// Fetch comments when mounted on the client
...
...
src/views/UserView.vue
View file @
6c9dd49a
...
@@ -30,11 +30,14 @@ export default {
...
@@ -30,11 +30,14 @@ export default {
}
}
},
},
asyncData
({
store
,
route
:
{
params
:
{
id
}},
ssrContext
})
{
asyncData
({
store
,
route
:
{
params
:
{
id
}}})
{
return
store
.
dispatch
(
'FETCH_USER'
,
{
id
}).
then
(()
=>
{
return
store
.
dispatch
(
'FETCH_USER'
,
{
id
})
const
user
=
store
.
state
.
users
[
id
]
},
setTitle
(
user
?
user
.
id
:
'User not found'
,
ssrContext
)
})
title
()
{
return
this
.
user
?
this
.
user
.
id
:
'User not found'
}
}
}
}
</
script
>
</
script
>
...
...
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