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>
<nuxt-container>
<nuxt/>
<component :is="layout"></component>
</nuxt-container>
</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) {
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))

View File

@ -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

View File

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

View File

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

View File

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