Add layout feature

This commit is contained in:
Sébastien Chopin 2016-12-24 01:55:32 +01:00
parent 6b9af524aa
commit b870a7206e
6 changed files with 63 additions and 12 deletions

View File

@ -1,5 +1,28 @@
<template> <template>
<nuxt-container> <nuxt-container>
<nuxt/> <component :is="layout"></component>
</nuxt-container> </nuxt-container>
</template> </template>
<script>
let layouts = {
<%
var layoutsKeys = Object.keys(layouts);
layoutsKeys.forEach(function (key, i) { %>
_<%= key %>: require('<%= layouts[key] %>')<%= (i + 1) < layoutsKeys.length ? ',' : '' %>
<% }) %>
}
export default {
data () {
return { layout: layouts._default }
},
methods: {
setLayout (layout) {
if (!layout || !layouts['_' + layout]) layout = 'default'
this.layout = layouts['_' + layout]
return layout
}
}
}
</script>

View File

@ -66,17 +66,20 @@ function render (to, from, next) {
if (!Component._data) { if (!Component._data) {
Component._data = Component.options.data || noopData 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 Component.options.fetch = Component._Ctor.options.fetch
const originalDataFn = Component._data.toString().replace(/\s/g, '') if (Component._dataFn) {
const dataFn = Component._dataFn const originalDataFn = Component._data.toString().replace(/\s/g, '')
const newDataFn = (Component._Ctor.options.data || noopData).toString().replace(/\s/g, '') const dataFn = Component._dataFn
// If component data method changed const newDataFn = (Component._Ctor.options.data || noopData).toString().replace(/\s/g, '')
if (newDataFn !== originalDataFn && newDataFn !== dataFn) { // If component data method changed
Component._data = Component._Ctor.options.data || noopData 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.setTransitions(mapTransitions(Components, to, from))
this.error() this.error()
let nextCalled = false let nextCalled = false
@ -172,6 +175,7 @@ function hotReloadAPI (_app) {
Component = Vue.extend(Component) Component = Vue.extend(Component)
Component._Ctor = Component Component._Ctor = Component
} }
_app.setLayout(Component.options.layout)
let promises = [] let promises = []
const next = function (path) { const next = function (path) {
<%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %> <%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %>
@ -281,6 +285,9 @@ Promise.all(resolveComponents)
store.replaceState(NUXT.state) store.replaceState(NUXT.state)
} }
<% } %> <% } %>
if (Components.length) {
_app.setLayout(Components[0].options.layout)
}
_app.setTransitions = _app.$options._nuxt.setTransitions.bind(_app) _app.setTransitions = _app.$options._nuxt.setTransitions.bind(_app)
if (Components.length) { if (Components.length) {
_app.setTransitions(mapTransitions(Components, router.currentRoute)) _app.setTransitions(mapTransitions(Components, router.currentRoute))

View File

@ -22,6 +22,8 @@ export default {
Vue.prototype.$nuxt = this Vue.prototype.$nuxt = this
// Add this.$root.$nuxt // Add this.$root.$nuxt
this.$root.$nuxt = this 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 // add to window so we can listen when ready
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
window.$nuxt = this window.$nuxt = this

View File

@ -0,0 +1,3 @@
<template>
<nuxt/>
</template>

View File

@ -73,6 +73,10 @@ export default context => {
} }
return Component return Component
}) })
// Set layout
if (Components.length && Components[0].options.layout) {
_app.setLayout(Components[0].options.layout)
}
// Call .validate() // Call .validate()
let isValid = true let isValid = true
Components.forEach((Component) => { Components.forEach((Component) => {

View File

@ -132,6 +132,14 @@ function * buildFiles () {
function * generateRoutesAndFiles () { function * generateRoutesAndFiles () {
debug('Generating routes...') 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 // Generate routes based on files
const files = yield glob('pages/**/*.vue', { cwd: this.srcDir }) const files = yield glob('pages/**/*.vue', { cwd: this.srcDir })
this.routes = _.uniq(_.map(files, (file) => { this.routes = _.uniq(_.map(files, (file) => {
@ -165,6 +173,7 @@ function * generateRoutesAndFiles () {
css: this.options.css, css: this.options.css,
plugins: this.options.plugins.map((p) => r(this.srcDir, p)), plugins: this.options.plugins.map((p) => r(this.srcDir, p)),
appPath: './App.vue', appPath: './App.vue',
layouts: layouts,
loading: (typeof this.options.loading === 'string' ? r(this.srcDir, this.options.loading) : this.options.loading), loading: (typeof this.options.loading === 'string' ? r(this.srcDir, this.options.loading) : this.options.loading),
transition: this.options.transition, transition: this.options.transition,
components: { components: {
@ -174,12 +183,15 @@ function * generateRoutesAndFiles () {
} }
// Format routes for the lib/app/router.js template // Format routes for the lib/app/router.js template
templateVars.router.routes = createRoutes(files, this.srcDir) templateVars.router.routes = createRoutes(files, this.srcDir)
if (fs.existsSync(join(this.srcDir, 'layouts', 'app.vue'))) { if (layoutsFiles.includes('layouts/error.vue')) {
templateVars.appPath = r(this.srcDir, 'layouts/app.vue')
}
if (fs.existsSync(join(this.srcDir, 'layouts', 'error.vue'))) {
templateVars.components.ErrorPage = r(this.srcDir, '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) => { let moveTemplates = templatesFiles.map((file) => {
return readFile(r(__dirname, 'app', file), 'utf8') return readFile(r(__dirname, 'app', file), 'utf8')
.then((fileContent) => { .then((fileContent) => {