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) => {