diff --git a/examples/vuex-store-2/README.md b/examples/vuex-store-2/README.md new file mode 100644 index 0000000000..8146795f6c --- /dev/null +++ b/examples/vuex-store-2/README.md @@ -0,0 +1,94 @@ +# Nuxt.js with Vuex 2 + +> Using a store to manage the state is important to every big application, that's why nuxt.js implement Vuex in its core. + +> Alternative way of creating a store modularly. + +## Activating the store + +Nuxt.js will look for the `./store/` directory, if it exists, its will import and use Vuex. If there is no `./store/index.js` file that returns a store, Nuxt.js will go through all files of the `./store/` directory and create a store with a module for each file (`./store/index.js` being "root" module). + +## Create the store folder + +Let's create a file `store/index.js`: + +```js +export const state = { counter: 0 } + +export const mutations = { + increment (state) { + state.counter++ + } +} +``` + +and +`store/todos.js`: + +```js +export const state = { + list: [] +} + +export const mutations = { + add (state, { text }) { + state.list.push({ + text, + done: false + }) + }, + + delete (state, { todo }) { + state.list.splice(state.list.indexOf(todo), 1) + }, + + toggle (state, { todo }) { + todo.done = !todo.done + } +} +``` + +> We don't need to install `Vuex` since it's shipped with nuxt.js + +## VoilĂ  ! + +We can now use `this.$store` inside our `.vue` files. + +```html + +``` + +The store will be as such: +```js +new Vuex.Store({ + state: { counter: 0 }, + mutations: { + increment (state) { + state.counter++ + } + }, + modules: { + todos: { + state: { + list: [] + }, + mutations: { + add (state, { text }) { + state.list.push({ + text, + done: false + }) + }, + delete (state, { todo }) { + state.list.splice(state.list.indexOf(todo), 1) + }, + toggle (state, { todo }) { + todo.done = !todo.done + } + } + } + } +}) +``` diff --git a/examples/vuex-store-2/package.json b/examples/vuex-store-2/package.json new file mode 100644 index 0000000000..3bd4273fa4 --- /dev/null +++ b/examples/vuex-store-2/package.json @@ -0,0 +1,11 @@ +{ + "name": "nuxt-vuex-store", + "dependencies": { + "nuxt": "latest" + }, + "scripts": { + "dev": "nuxt", + "build": "nuxt build", + "start": "nuxt start" + } +} diff --git a/examples/vuex-store-2/pages/about.vue b/examples/vuex-store-2/pages/about.vue new file mode 100644 index 0000000000..f489bfe089 --- /dev/null +++ b/examples/vuex-store-2/pages/about.vue @@ -0,0 +1,8 @@ + diff --git a/examples/vuex-store-2/pages/index.vue b/examples/vuex-store-2/pages/index.vue new file mode 100644 index 0000000000..55131f0fee --- /dev/null +++ b/examples/vuex-store-2/pages/index.vue @@ -0,0 +1,29 @@ + + + diff --git a/examples/vuex-store-2/pages/todos.vue b/examples/vuex-store-2/pages/todos.vue new file mode 100644 index 0000000000..7b5d30dfb3 --- /dev/null +++ b/examples/vuex-store-2/pages/todos.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/examples/vuex-store-2/store/index.js b/examples/vuex-store-2/store/index.js new file mode 100644 index 0000000000..a4521c2fc2 --- /dev/null +++ b/examples/vuex-store-2/store/index.js @@ -0,0 +1,7 @@ +export const state = { counter: 0 } + +export const mutations = { + increment (state) { + state.counter++ + } +} diff --git a/examples/vuex-store-2/store/todos.js b/examples/vuex-store-2/store/todos.js new file mode 100644 index 0000000000..ca87fe5a3f --- /dev/null +++ b/examples/vuex-store-2/store/todos.js @@ -0,0 +1,20 @@ +export const state = { + list: [] +} + +export const mutations = { + add (state, { text }) { + state.list.push({ + text, + done: false + }) + }, + + delete (state, { todo }) { + state.list.splice(state.list.indexOf(todo), 1) + }, + + toggle (state, { todo }) { + todo.done = !todo.done + } +} diff --git a/lib/app/index.js b/lib/app/index.js index 3007b76901..fb215f219d 100644 --- a/lib/app/index.js +++ b/lib/app/index.js @@ -4,7 +4,7 @@ require('es6-object-assign').polyfill() import Vue from 'vue' import Meta from 'vue-meta' import router from './router.js' -<% if (store) { %>import store from '~store/index.js'<% } %> +<% if (store) { %>import store from './store.js'<% } %> import NuxtChild from './components/nuxt-child.js' import NuxtLink from './components/nuxt-link.js' import Nuxt from './components/nuxt.vue' diff --git a/lib/app/store.js b/lib/app/store.js new file mode 100644 index 0000000000..adbc0ec4d2 --- /dev/null +++ b/lib/app/store.js @@ -0,0 +1,47 @@ +import Vue from 'vue' +import Vuex from 'vuex' +Vue.use(Vuex) + +let files +let filenames = [] + +try { + files = require.context('~store', false, /^\.\/.*\.js$/) + filenames = files.keys() +} catch (e) { + console.warn('Nuxt.js store:', e.message) +} + +function getModule (filename) { + let file = files(filename) + return file.default + ? file.default + : file +} + +let store +let storeData = {} + +// Check if store/index.js returns a vuex store +if (filenames.indexOf('./index.js') !== -1) { + let mainModule = getModule('./index.js') + if (mainModule.commit) { + store = mainModule + } else { + storeData = mainModule + } +} + +// Generate the store if there is no store yet +if (store == null) { + storeData.modules = storeData.modules || {} + for (let filename of filenames) { + let name = filename.replace(/^\.\//, '').replace(/\.js$/, '') + if (name === 'index') continue + storeData.modules[name] = getModule(filename) + storeData.modules[name].namespaced = true + } + store = new Vuex.Store(storeData) +} + +export default store diff --git a/lib/build/index.js b/lib/build/index.js index 4afca04448..2007ee69d2 100644 --- a/lib/build/index.js +++ b/lib/build/index.js @@ -191,6 +191,10 @@ function * generateRoutesAndFiles () { templatesFiles.push('layouts/default.vue') layouts.default = r(__dirname, 'app', 'layouts', 'default.vue') } + // Add store if needed + if (this.options.store) { + templatesFiles.push('store.js') + } let moveTemplates = templatesFiles.map((file) => { return readFile(r(__dirname, 'app', file), 'utf8') .then((fileContent) => { diff --git a/lib/nuxt.js b/lib/nuxt.js index a3ca5b06c8..cdfa088c92 100644 --- a/lib/nuxt.js +++ b/lib/nuxt.js @@ -51,7 +51,7 @@ class Nuxt { this.dir = (typeof options.rootDir === 'string' && options.rootDir ? options.rootDir : process.cwd()) this.srcDir = (typeof options.srcDir === 'string' && options.srcDir ? resolve(this.dir, options.srcDir) : this.dir) // If store defined, update store options to true - if (fs.existsSync(join(this.srcDir, 'store', 'index.js'))) { + if (fs.existsSync(join(this.srcDir, 'store'))) { this.options.store = true } // Template