diff --git a/lib/app/App.vue b/lib/app/App.vue
index 25fab4ce30..b3ecb7b7af 100644
--- a/lib/app/App.vue
+++ b/lib/app/App.vue
@@ -1,5 +1,28 @@
-
+
+
+
diff --git a/lib/app/client.js b/lib/app/client.js
index 8f01a7dd13..7e1c226ad1 100644
--- a/lib/app/client.js
+++ b/lib/app/client.js
@@ -66,17 +66,20 @@ function render (to, from, next) {
if (!Component._data) {
Component._data = Component.options.data || noopData
}
- if (Component._Ctor && Component._Ctor.options && Component._dataFn) {
+ if (Component._Ctor && Component._Ctor.options) {
Component.options.fetch = Component._Ctor.options.fetch
- const originalDataFn = Component._data.toString().replace(/\s/g, '')
- const dataFn = Component._dataFn
- const newDataFn = (Component._Ctor.options.data || noopData).toString().replace(/\s/g, '')
- // If component data method changed
- if (newDataFn !== originalDataFn && newDataFn !== dataFn) {
- Component._data = Component._Ctor.options.data || noopData
+ if (Component._dataFn) {
+ const originalDataFn = Component._data.toString().replace(/\s/g, '')
+ const dataFn = Component._dataFn
+ const newDataFn = (Component._Ctor.options.data || noopData).toString().replace(/\s/g, '')
+ // If component data method changed
+ if (newDataFn !== originalDataFn && newDataFn !== dataFn) {
+ Component._data = Component._Ctor.options.data || noopData
+ }
}
}
})
+ this.setLayout(Components[0].options.layout)
this.setTransitions(mapTransitions(Components, to, from))
this.error()
let nextCalled = false
@@ -172,6 +175,7 @@ function hotReloadAPI (_app) {
Component = Vue.extend(Component)
Component._Ctor = Component
}
+ _app.setLayout(Component.options.layout)
let promises = []
const next = function (path) {
<%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %>
@@ -281,6 +285,9 @@ Promise.all(resolveComponents)
store.replaceState(NUXT.state)
}
<% } %>
+ if (Components.length) {
+ _app.setLayout(Components[0].options.layout)
+ }
_app.setTransitions = _app.$options._nuxt.setTransitions.bind(_app)
if (Components.length) {
_app.setTransitions(mapTransitions(Components, router.currentRoute))
diff --git a/lib/app/components/nuxt.vue b/lib/app/components/nuxt.vue
index 743984a1b7..759103073a 100644
--- a/lib/app/components/nuxt.vue
+++ b/lib/app/components/nuxt.vue
@@ -22,6 +22,8 @@ export default {
Vue.prototype.$nuxt = this
// Add this.$root.$nuxt
this.$root.$nuxt = this
+ // Bind $nuxt.setLayout(layout) to $root.setLayout
+ this.setLayout = this.$root.setLayout.bind(this.$root)
// add to window so we can listen when ready
if (typeof window !== 'undefined') {
window.$nuxt = this
diff --git a/lib/app/layouts/default.vue b/lib/app/layouts/default.vue
new file mode 100644
index 0000000000..2cc8469e52
--- /dev/null
+++ b/lib/app/layouts/default.vue
@@ -0,0 +1,3 @@
+
+
+
diff --git a/lib/app/server.js b/lib/app/server.js
index c458729d5d..2846e56716 100644
--- a/lib/app/server.js
+++ b/lib/app/server.js
@@ -73,6 +73,10 @@ export default context => {
}
return Component
})
+ // Set layout
+ if (Components.length && Components[0].options.layout) {
+ _app.setLayout(Components[0].options.layout)
+ }
// Call .validate()
let isValid = true
Components.forEach((Component) => {
diff --git a/lib/build/index.js b/lib/build/index.js
index 8d47588799..7d9eca8fff 100644
--- a/lib/build/index.js
+++ b/lib/build/index.js
@@ -132,6 +132,14 @@ function * buildFiles () {
function * generateRoutesAndFiles () {
debug('Generating routes...')
+ // Layouts
+ let layouts = {}
+ const layoutsFiles = yield glob('layouts/*.vue', { cwd: this.srcDir })
+ layoutsFiles.forEach((file) => {
+ let name = file.split('/').slice(-1)[0].replace('.vue', '')
+ if (name === 'error') return
+ layouts[name] = r(this.srcDir, file)
+ })
// Generate routes based on files
const files = yield glob('pages/**/*.vue', { cwd: this.srcDir })
this.routes = _.uniq(_.map(files, (file) => {
@@ -165,6 +173,7 @@ function * generateRoutesAndFiles () {
css: this.options.css,
plugins: this.options.plugins.map((p) => r(this.srcDir, p)),
appPath: './App.vue',
+ layouts: layouts,
loading: (typeof this.options.loading === 'string' ? r(this.srcDir, this.options.loading) : this.options.loading),
transition: this.options.transition,
components: {
@@ -174,12 +183,15 @@ function * generateRoutesAndFiles () {
}
// Format routes for the lib/app/router.js template
templateVars.router.routes = createRoutes(files, this.srcDir)
- if (fs.existsSync(join(this.srcDir, 'layouts', 'app.vue'))) {
- templateVars.appPath = r(this.srcDir, 'layouts/app.vue')
- }
- if (fs.existsSync(join(this.srcDir, 'layouts', 'error.vue'))) {
+ if (layoutsFiles.includes('layouts/error.vue')) {
templateVars.components.ErrorPage = r(this.srcDir, 'layouts/error.vue')
}
+ // If no default layout, create its folder and add the default folder
+ if (!layouts.default) {
+ yield mkdirp(r(this.dir, '.nuxt/layouts'))
+ templatesFiles.push('layouts/default.vue')
+ layouts.default = r(__dirname, 'app', 'layouts', 'default.vue')
+ }
let moveTemplates = templatesFiles.map((file) => {
return readFile(r(__dirname, 'app', file), 'utf8')
.then((fileContent) => {