Fix due 2.0.6~7 and add error() in context

This commit is contained in:
Sébastien Chopin 2016-11-17 11:57:02 +01:00
parent 8b4c2e0e53
commit 2677afb46f
7 changed files with 63 additions and 28 deletions

View File

@ -11,9 +11,12 @@
import axios from 'axios' import axios from 'axios'
export default { export default {
data ({ params }) { data ({ params, error }) {
return axios.get(`http://jsonplaceholder.typicode.com/users/${params.id}`) return axios.get(`http://jsonplaceholder.typicode.com/users/${params.id}`)
.then((res) => res.data) .then((res) => res.data)
.catch(() => {
error({ message: 'User not found', statusCode: 404 })
})
} }
} }
</script> </script>

View File

@ -2,10 +2,21 @@
<div class="container"> <div class="container">
<img src="~static/nuxt-black.png" /> <img src="~static/nuxt-black.png" />
<h2>Thank you for testing nuxt.js</h2> <h2>Thank you for testing nuxt.js</h2>
<p>Loaded from the {{ name }}</p>
<p><router-link to="/">Back home</router-link></p> <p><router-link to="/">Back home</router-link></p>
</div> </div>
</template> </template>
<script>
export default {
data ({ req, error }) {
return {
name: req ? 'server' : 'client'
}
}
}
</script>
<style scoped> <style scoped>
.container { .container {
position: absolute; position: absolute;

View File

@ -30,6 +30,7 @@ test.before('Init nuxt.js', (t) => {
// Function used to do dom checking via jsdom // Function used to do dom checking via jsdom
async function renderAndGetWindow (route) { async function renderAndGetWindow (route) {
const virtualConsole = jsdom.createVirtualConsole().sendTo(console)
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const url = 'http://localhost:4000' + route const url = 'http://localhost:4000' + route
jsdom.env({ jsdom.env({
@ -38,6 +39,7 @@ async function renderAndGetWindow (route) {
FetchExternalResources: ['script', 'link'], FetchExternalResources: ['script', 'link'],
ProcessExternalResources: ['script'] ProcessExternalResources: ['script']
}, },
virtualConsole,
done (err, window) { done (err, window) {
if (err) return reject(err) if (err) return reject(err)
// If Nuxt could not be loaded (error from the server-side) // If Nuxt could not be loaded (error from the server-side)

View File

@ -14,13 +14,20 @@ function loadAsyncComponents (to, ___, next) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
const _resolve = (Component) => { const _resolve = (Component) => {
// console.log('Component loaded', Component, match.path, key) // console.log('Component loaded', Component, match.path, key)
Component = Vue.extend(Component) // fix issue #6
Component._Ctor = Component
match.components[key] = Component match.components[key] = Component
resolve(Component) resolve(Component)
} }
Component().then(_resolve).catch(reject) Component().then(_resolve).catch(reject)
}) })
} }
// console.log('Return Component', match) if (typeof Component === 'object' && !Component.options) {
// Updated via vue-router resolveAsyncComponents()
Component = Vue.extend(Component)
Component._Ctor = Component
match.components[key] = Component
}
return Component return Component
}) })
<%= (loading ? 'this.$loading.start && this.$loading.start()' : '') %> <%= (loading ? 'this.$loading.start && this.$loading.start()' : '') %>
@ -42,12 +49,12 @@ function render (to, ___, next) {
// Update ._data and other properties if hot reloaded // Update ._data and other properties if hot reloaded
Components.forEach(function (Component) { Components.forEach(function (Component) {
if (!Component._data) { if (!Component._data) {
Component._data = Component.data || noopData Component._data = Component.options.data || noopData
} }
if (Component._Ctor && Component._Ctor.options) { if (Component._Ctor && Component._Ctor.options && Component._dataFn) {
Component.fetch = Component._Ctor.options.fetch Component.options.fetch = Component._Ctor.options.fetch
const originalDataFn = Component._data.toString().replace(/\s/g, '') const originalDataFn = Component._data.toString().replace(/\s/g, '')
const dataFn = (Component.data || noopData).toString().replace(/\s/g, '') const dataFn = Component._dataFn
const newDataFn = (Component._Ctor.options.data || noopData).toString().replace(/\s/g, '') const newDataFn = (Component._Ctor.options.data || noopData).toString().replace(/\s/g, '')
// If component data method changed // If component data method changed
if (newDataFn !== originalDataFn && newDataFn !== dataFn) { if (newDataFn !== originalDataFn && newDataFn !== dataFn) {
@ -64,21 +71,22 @@ function render (to, ___, next) {
nextCalled = true nextCalled = true
next(path) next(path)
} }
const context = getContext({ to<%= (store ? ', store' : '') %>, isClient: true, next: _next.bind(this) }) const context = getContext({ to<%= (store ? ', store' : '') %>, isClient: true, next: _next.bind(this), error: this.error.bind(this) })
if (Component._data && typeof Component._data === 'function') { if (Component._data && typeof Component._data === 'function') {
var promise = Component._data(context) var promise = Component._data(context)
if (!(promise instanceof Promise)) promise = Promise.resolve(promise) if (!(promise instanceof Promise)) promise = Promise.resolve(promise)
promise.then((data) => { promise.then((data) => {
Component.data = () => data Component.options.data = () => data || {}
Component._dataFn = Component.options.data.toString().replace(/\s/g, '')
if (Component._Ctor && Component._Ctor.options) { if (Component._Ctor && Component._Ctor.options) {
Component._Ctor.options.data = Component.data Component._Ctor.options.data = Component.options.data
} }
<%= (loading ? 'this.$loading.increase && this.$loading.increase(30)' : '') %> <%= (loading ? 'this.$loading.increase && this.$loading.increase(30)' : '') %>
}) })
promises.push(promise) promises.push(promise)
} }
if (Component.fetch) { if (Component.options.fetch) {
var p = Component.fetch(context) var p = Component.options.fetch(context)
if (!(p instanceof Promise)) { p = Promise.resolve(p) } if (!(p instanceof Promise)) { p = Promise.resolve(p) }
<%= (loading ? 'p.then(() => this.$loading.increase && this.$loading.increase(30))' : '') %> <%= (loading ? 'p.then(() => this.$loading.increase && this.$loading.increase(30))' : '') %>
promises.push(p) promises.push(p)
@ -110,7 +118,7 @@ function hotReloadAPI (_app) {
<%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %> <%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %>
router.push(path) router.push(path)
} }
const context = getContext({ route: router.currentRoute<%= (store ? ', store' : '') %>, isClient: true, next: next.bind(this) }) const context = getContext({ route: router.currentRoute<%= (store ? ', store' : '') %>, isClient: true, next: next.bind(this), error: _app.error.bind(_app) })
// Check if data has been updated // Check if data has been updated
const originalDataFn = (Component._data || noopData).toString().replace(/\s/g, '') const originalDataFn = (Component._data || noopData).toString().replace(/\s/g, '')
const newDataFn = (Component._Ctor.options.data || noopData).toString().replace(/\s/g, '') const newDataFn = (Component._Ctor.options.data || noopData).toString().replace(/\s/g, '')
@ -119,19 +127,20 @@ function hotReloadAPI (_app) {
let p = Component._data(context) let p = Component._data(context)
if (!(p instanceof Promise)) { p = Promise.resolve(p) } if (!(p instanceof Promise)) { p = Promise.resolve(p) }
p.then((data) => { p.then((data) => {
Component.data = () => data Component.options.data = () => data || {}
Component._Ctor.options.data = Component.data Component._dataFn = Component.options.data.toString().replace(/\s/g, '')
Component._Ctor.options.data = Component.options.data
<%= (loading ? 'this.$loading.increase && this.$loading.increase(30)' : '') %> <%= (loading ? 'this.$loading.increase && this.$loading.increase(30)' : '') %>
}) })
promises.push(p) promises.push(p)
} }
// Check if fetch has been updated // Check if fetch has been updated
const originalFetchFn = (Component.fetch || noopFetch).toString().replace(/\s/g, '') const originalFetchFn = (Component.options.fetch || noopFetch).toString().replace(/\s/g, '')
const newFetchFn = (Component._Ctor.options.fetch || noopFetch).toString().replace(/\s/g, '') const newFetchFn = (Component._Ctor.options.fetch || noopFetch).toString().replace(/\s/g, '')
// Fetch has been updated, we call it to update the store // Fetch has been updated, we call it to update the store
if (originalFetchFn !== newFetchFn) { if (originalFetchFn !== newFetchFn) {
Component.fetch = Component._Ctor.options.fetch || noopFetch Component.options.fetch = Component._Ctor.options.fetch || noopFetch
let p = Component.fetch(context) let p = Component.options.fetch(context)
if (!(p instanceof Promise)) { p = Promise.resolve(p) } if (!(p instanceof Promise)) { p = Promise.resolve(p) }
<%= (loading ? 'p.then(() => this.$loading.increase && this.$loading.increase(30))' : '') %> <%= (loading ? 'p.then(() => this.$loading.increase && this.$loading.increase(30))' : '') %>
promises.push(p) promises.push(p)
@ -160,13 +169,16 @@ const resolveComponents = flatMapComponents(router.match(path), (Component, _, m
if (typeof Component === 'function' && !Component.options) { if (typeof Component === 'function' && !Component.options) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
const _resolve = (Component) => { const _resolve = (Component) => {
if (Component.data && typeof Component.data === 'function') { Component = Vue.extend(Component) // fix issue #6
Component._data = Component.data Component._Ctor = Component
if (Component.options.data && typeof Component.options.data === 'function') {
Component._data = Component.options.data
if (NUXT.serverRendered) { if (NUXT.serverRendered) {
Component.data = () => NUXT.data[index] Component.options.data = () => NUXT.data[index] || {}
Component._dataFn = Component.options.data.toString().replace(/\s/g, '')
} }
if (Component._Ctor && Component._Ctor.options) { if (Component._Ctor && Component._Ctor.options) {
Component._Ctor.options.data = Component.data Component._Ctor.options.data = Component.options.data
} }
} }
match.components[key] = Component match.components[key] = Component

View File

@ -45,6 +45,8 @@ export default context => {
context.route = router.currentRoute context.route = router.currentRoute
// Add meta infos // Add meta infos
context.meta = _app.$meta() context.meta = _app.$meta()
// Error function
context.error = _app.error.bind(_app)
<%= (isDev ? 'const s = isDev && Date.now()' : '') %> <%= (isDev ? 'const s = isDev && Date.now()' : '') %>
// Call data & fecth hooks on components matched by the route. // Call data & fecth hooks on components matched by the route.
@ -62,6 +64,9 @@ export default context => {
if (!(promise instanceof Promise)) promise = Promise.resolve(promise) if (!(promise instanceof Promise)) promise = Promise.resolve(promise)
promise.then((data) => { promise.then((data) => {
Component.data = () => data Component.data = () => data
if (Component._Ctor) {
Component._Ctor = Vue.extend(Component)
}
}) })
promises.push(promise) promises.push(promise)
} else { } else {
@ -78,6 +83,7 @@ export default context => {
<% } %> <% } %>
// datas are the first row of each // datas are the first row of each
context.nuxt.data = res.map((tab) => tab[0]) context.nuxt.data = res.map((tab) => tab[0])
context.nuxt.error = _app.err
<%= (store ? '// Add the state from the vuex store' : '') %> <%= (store ? '// Add the state from the vuex store' : '') %>
<%= (store ? 'context.nuxt.state = store.state' : '') %> <%= (store ? 'context.nuxt.state = store.state' : '') %>
return _app return _app

View File

@ -21,7 +21,8 @@ export function getContext (context) {
isServer: !!context.isServer, isServer: !!context.isServer,
isClient: !!context.isClient, isClient: !!context.isClient,
<%= (store ? 'store: context.store,' : '') %> <%= (store ? 'store: context.store,' : '') %>
route: (context.to ? context.to : context.route) route: (context.to ? context.to : context.route),
error: context.error
} }
ctx.params = ctx.route.params || {} ctx.params = ctx.route.params || {}
ctx.query = ctx.route.query || {} ctx.query = ctx.route.query || {}

View File

@ -1,6 +1,6 @@
{ {
"name": "nuxt", "name": "nuxt",
"version": "0.4.3", "version": "0.4.4",
"description": "A minimalistic framework for server-rendered Vue.js applications (inspired by Next.js)", "description": "A minimalistic framework for server-rendered Vue.js applications (inspired by Next.js)",
"main": "index.js", "main": "index.js",
"license": "MIT", "license": "MIT",
@ -41,11 +41,11 @@
"serialize-javascript": "^1.3.0", "serialize-javascript": "^1.3.0",
"serve-static": "^1.11.1", "serve-static": "^1.11.1",
"url-loader": "^0.5.7", "url-loader": "^0.5.7",
"vue": "^2.0.5", "vue": "^2.0.7",
"vue-loader": "^9.8.0", "vue-loader": "^9.9.5",
"vue-meta": "^0.4.1", "vue-meta": "^0.4.4",
"vue-router": "^2.0.1", "vue-router": "^2.0.2",
"vue-server-renderer": "^2.0.5", "vue-server-renderer": "^2.0.7",
"vuex": "^2.0.0", "vuex": "^2.0.0",
"webpack": "2.1.0-beta.26", "webpack": "2.1.0-beta.26",
"webpack-dev-middleware": "^1.8.4", "webpack-dev-middleware": "^1.8.4",