Nuxt + Vuex - 如何将 Vuex 模块分解为单独的文件?
Nuxt + Vuex - How do I break down a Vuex module into separate files?
在 Nuxt 文档 (here) 中说 'You can optionally break down a module file into separate files: state.js
, actions.js
, mutations.js
and getters.js
.'
我似乎找不到任何关于如何做到这一点的例子——很多在根级别将 Vuex 存储分解为 state.js
、actions.js
、mutations.js
和getters.js
,并进入单独的模块文件,但与分解模块本身无关。
所以目前我有:
├── assets
├── components
└── store
├── moduleOne.js
├── moduleTwo.js
└── etc...
而我想要的是:
├── assets
├── components
└── store
└── moduleOne
└── state.js
└── getters.js
└── mutations.js
└── actions.js
└── moduleTwo
└── etc...
为了尝试这个,在 /store/moduleOne/state.js
我有:
export const state = () => {
return {
test: 'test'
}
};
在 /store/moduleOne/getters.js
我有:
export const getters = {
getTest (state) {
return state.test;
}
}
在我的组件中,我使用 $store.getters['moduleOne/getters/getTest']
访问它
但是使用调试器和 Vue devtools,在 getters 文件中似乎无法访问状态 - 它似乎在本地文件中寻找状态,因此 state.test
未定义。
尝试将 state
从我的 state.js
文件导入到我的 getters.js
文件似乎也不起作用。
有没有人举例说明他们如何在 Nuxt 中像这样分解商店?
你的问题
在您的文件中使用 default
导出来达到预期效果(除了 index.js
中没有命名导出)
例子
示例可以直接在 Nuxt.js 测试套件(位于 https://github.com/nuxt/nuxt.js/tree/dev/test/fixtures/basic/store/foo)中找到。
如果您 运行 basic
装置并访问 /store 页面,您将看到以下结果
模块本身的“重复”内容只是表明拆分值优先(否则 getVal
不会 return 10 但 99 和 state.val
不会'不是 4 而是 2).
store.vue代码:
<template>
<div>
<h1>{{ baz }}</h1>
<br>
<p>{{ $store.state.counter }}</p>
<br>
<h2>{{ getVal }}</h2>
<br>
<h3>{{ getBabVal }}</h3>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters('foo/bar', ['baz']),
...mapGetters('foo/blarg', ['getVal']),
...mapGetters('bab', ['getBabVal'])
}
}
</script>
我正在使用 nuxt 2.1.0
如果你想要这样的东西:
在我的store/index.js
确保你有 namespaced: true
import Vuex from 'vuex';
import apiModule from './modules/api-logic';
import appModule from './modules/app-logic';
const createStore = () => {
return new Vuex.Store({
namespaced: true,
modules: {
appLogic: appModule,
api: apiModule
}
});
};
export default createStore
在模块一中
在我的store/api-logic/index.js
import actions from './actions';
import getters from './getters';
import mutations from './mutations';
const defaultState = {
hello: 'salut I am module api'
}
const inBrowser = typeof window !== 'undefined';
// if in browser, use pre-fetched state injected by SSR
const state = (inBrowser && window.__INITIAL_STATE__) ? window.__INITIAL_STATE__.page : defaultState;
export default {
state,
actions,
mutations,
getters
}
在我的store/api-logic/getters.js
export default {
getHelloThere: state => state.hello
}
在模块二中
在我的store/app-logic/index.js
import actions from './actions';
import getters from './getters';
import mutations from './mutations';
const defaultState = {
appLogicData: 'bonjours I am module Logic'
}
const inBrowser = typeof window !== 'undefined';
// if in browser, use pre-fetched state injected by SSR
const state = (inBrowser && window.__INITIAL_STATE__) ? window.__INITIAL_STATE__.page : defaultState;
export default {
state,
actions,
mutations,
getters
}
在我的store/app-logic/getters.js
export default {
getAppLogicData: state => state.appLogicData
}
应用程序中的任何位置
computed: {
...mapGetters({
logicData: 'getAppLogicData',
coucou: 'getHelloThere'
})
},
mounted () {
console.log('coucou', this.coucou) --> salut I am module api
console.log('logicData', this.logicData) --> bonjours I am module Logic
}
奖励积分
如果您想在模块之间进行通信,例如应用程序逻辑中的一个动作会触发 api-逻辑中的某些内容。
所以应用程序逻辑(模块一)到 api-逻辑(模块二)
当您指定 root: true
时,它将开始查看商店的根目录。
在store/app-logic/actions.js
callPokemonFromAppLogic: ({ dispatch }, id) => {
dispatch('callThePokemonFromApiLogic', id, {root:true});
},
在store/api-logic/actions.js
callThePokemonFromApiLogic: ({ commit }, id) => {
console.log('I make the call here')
axios.get('http://pokeapi.salestock.net/api/v2/pokemon/' + id).then(response => commit('update_pokemon', response.data))
},
在store/api-logic/index.js
中添加另一个条目
import actions from './actions';
import getters from './getters';
import mutations from './mutations';
const defaultState = {
appLogicData: 'bonjours I am module Logic',
pokemon: {}
}
const inBrowser = typeof window !== 'undefined';
// if in browser, use pre-fetched state injected by SSR
const state = (inBrowser && window.__INITIAL_STATE__) ? window.__INITIAL_STATE__.page : defaultState;
export default {
state,
actions,
mutations,
getters
}
在store/api-logic/mutations.js
中添加宠物小精灵突变:p
update_pokemon: (state, pokemon) => {
state.pokemon = pokemon
}
应用程序中的任何位置:
computed: {
...mapGetters({
bidule: 'bidule',
pokemon: 'getPokemon'
})
},
mounted() {
console.log('bidule', this.bidule)
this.callPokemonFromAppLogic('1') --> the call
console.log('the pokemon', this.pokemon.name) --> 'bulbasaur'
},
methods: {
...mapActions({
callPokemonFromAppLogic: 'callPokemonFromAppLogic'
}),
}
最后你的 Vue devTool 应该是这样的:)
瞧瞧,我希望很清楚。
代码示例:
在 nuxt 版本 2.14^ 中,您不必在商店根 index.js 文件中创建它。
import Vuex from 'vuex';
import apiModule from './modules/api-logic';
import appModule from './modules/app-logic';
const createStore = () => {
return new Vuex.Store({
namespaced: true,
modules: {
appLogic: appModule,
api: apiModule
}
});
};
export default createStore
但是,您可以将根 index.js 文件保留为默认文件或执行您需要的操作。无需导入。
store/index.js
export const state = () => ({
counter: 0
})
export const mutations = {
increment(state) {
state.counter++
}
}
export const actions = {
async nuxtServerInit({ state, commit }, { req }) {
const cookies = this.$cookies.getAll()
...
}
这是它的样子,非常简单。
文件夹结构
store
┣ auth
┣ utils
┣ posts
┃ ┗ actions.js
┃ ┗ mutations.js
┃ ┗ getters.js
┃ ┗ index.js
┣ index.js
例子
store/posts/index.js
你可以只放状态函数。您不需要导入动作、吸气剂和突变。
export const state = () => ({
comments: []
})
store/posts/actions.js
const actions = {
async getPosts({ commit, state }, obj) {
return new Promise((resolve, reject) => {
...
}
}
}
export default actions
store/posts/mutations.js
const mutations = {
CLEAR_POST_IMAGE_CONTENT: (state) => {
state.post_image_content = []
}
}
export default mutations
store/posts/getters.js
const getters = {
datatest: (state) => state.datatest,
headlineFeatures: (state) => state.headlineFeatures,
}
export default getters
效果与@CMarzin 的回答相同,但更清晰
在 Nuxt 文档 (here) 中说 'You can optionally break down a module file into separate files: state.js
, actions.js
, mutations.js
and getters.js
.'
我似乎找不到任何关于如何做到这一点的例子——很多在根级别将 Vuex 存储分解为 state.js
、actions.js
、mutations.js
和getters.js
,并进入单独的模块文件,但与分解模块本身无关。
所以目前我有:
├── assets
├── components
└── store
├── moduleOne.js
├── moduleTwo.js
└── etc...
而我想要的是:
├── assets
├── components
└── store
└── moduleOne
└── state.js
└── getters.js
└── mutations.js
└── actions.js
└── moduleTwo
└── etc...
为了尝试这个,在 /store/moduleOne/state.js
我有:
export const state = () => {
return {
test: 'test'
}
};
在 /store/moduleOne/getters.js
我有:
export const getters = {
getTest (state) {
return state.test;
}
}
在我的组件中,我使用 $store.getters['moduleOne/getters/getTest']
但是使用调试器和 Vue devtools,在 getters 文件中似乎无法访问状态 - 它似乎在本地文件中寻找状态,因此 state.test
未定义。
尝试将 state
从我的 state.js
文件导入到我的 getters.js
文件似乎也不起作用。
有没有人举例说明他们如何在 Nuxt 中像这样分解商店?
你的问题
在您的文件中使用 default
导出来达到预期效果(除了 index.js
中没有命名导出)
例子
示例可以直接在 Nuxt.js 测试套件(位于 https://github.com/nuxt/nuxt.js/tree/dev/test/fixtures/basic/store/foo)中找到。
如果您 运行 basic
装置并访问 /store 页面,您将看到以下结果
模块本身的“重复”内容只是表明拆分值优先(否则 getVal
不会 return 10 但 99 和 state.val
不会'不是 4 而是 2).
store.vue代码:
<template>
<div>
<h1>{{ baz }}</h1>
<br>
<p>{{ $store.state.counter }}</p>
<br>
<h2>{{ getVal }}</h2>
<br>
<h3>{{ getBabVal }}</h3>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters('foo/bar', ['baz']),
...mapGetters('foo/blarg', ['getVal']),
...mapGetters('bab', ['getBabVal'])
}
}
</script>
我正在使用 nuxt 2.1.0
如果你想要这样的东西:
在我的store/index.js
确保你有 namespaced: true
import Vuex from 'vuex';
import apiModule from './modules/api-logic';
import appModule from './modules/app-logic';
const createStore = () => {
return new Vuex.Store({
namespaced: true,
modules: {
appLogic: appModule,
api: apiModule
}
});
};
export default createStore
在模块一中
在我的store/api-logic/index.js
import actions from './actions';
import getters from './getters';
import mutations from './mutations';
const defaultState = {
hello: 'salut I am module api'
}
const inBrowser = typeof window !== 'undefined';
// if in browser, use pre-fetched state injected by SSR
const state = (inBrowser && window.__INITIAL_STATE__) ? window.__INITIAL_STATE__.page : defaultState;
export default {
state,
actions,
mutations,
getters
}
在我的store/api-logic/getters.js
export default {
getHelloThere: state => state.hello
}
在模块二中
在我的store/app-logic/index.js
import actions from './actions';
import getters from './getters';
import mutations from './mutations';
const defaultState = {
appLogicData: 'bonjours I am module Logic'
}
const inBrowser = typeof window !== 'undefined';
// if in browser, use pre-fetched state injected by SSR
const state = (inBrowser && window.__INITIAL_STATE__) ? window.__INITIAL_STATE__.page : defaultState;
export default {
state,
actions,
mutations,
getters
}
在我的store/app-logic/getters.js
export default {
getAppLogicData: state => state.appLogicData
}
应用程序中的任何位置
computed: {
...mapGetters({
logicData: 'getAppLogicData',
coucou: 'getHelloThere'
})
},
mounted () {
console.log('coucou', this.coucou) --> salut I am module api
console.log('logicData', this.logicData) --> bonjours I am module Logic
}
奖励积分
如果您想在模块之间进行通信,例如应用程序逻辑中的一个动作会触发 api-逻辑中的某些内容。 所以应用程序逻辑(模块一)到 api-逻辑(模块二)
当您指定 root: true
时,它将开始查看商店的根目录。
在store/app-logic/actions.js
callPokemonFromAppLogic: ({ dispatch }, id) => {
dispatch('callThePokemonFromApiLogic', id, {root:true});
},
在store/api-logic/actions.js
callThePokemonFromApiLogic: ({ commit }, id) => {
console.log('I make the call here')
axios.get('http://pokeapi.salestock.net/api/v2/pokemon/' + id).then(response => commit('update_pokemon', response.data))
},
在store/api-logic/index.js
中添加另一个条目
import actions from './actions';
import getters from './getters';
import mutations from './mutations';
const defaultState = {
appLogicData: 'bonjours I am module Logic',
pokemon: {}
}
const inBrowser = typeof window !== 'undefined';
// if in browser, use pre-fetched state injected by SSR
const state = (inBrowser && window.__INITIAL_STATE__) ? window.__INITIAL_STATE__.page : defaultState;
export default {
state,
actions,
mutations,
getters
}
在store/api-logic/mutations.js
中添加宠物小精灵突变:p
update_pokemon: (state, pokemon) => {
state.pokemon = pokemon
}
应用程序中的任何位置:
computed: {
...mapGetters({
bidule: 'bidule',
pokemon: 'getPokemon'
})
},
mounted() {
console.log('bidule', this.bidule)
this.callPokemonFromAppLogic('1') --> the call
console.log('the pokemon', this.pokemon.name) --> 'bulbasaur'
},
methods: {
...mapActions({
callPokemonFromAppLogic: 'callPokemonFromAppLogic'
}),
}
最后你的 Vue devTool 应该是这样的:)
瞧瞧,我希望很清楚。 代码示例:
在 nuxt 版本 2.14^ 中,您不必在商店根 index.js 文件中创建它。
import Vuex from 'vuex';
import apiModule from './modules/api-logic';
import appModule from './modules/app-logic';
const createStore = () => {
return new Vuex.Store({
namespaced: true,
modules: {
appLogic: appModule,
api: apiModule
}
});
};
export default createStore
但是,您可以将根 index.js 文件保留为默认文件或执行您需要的操作。无需导入。
store/index.js
export const state = () => ({
counter: 0
})
export const mutations = {
increment(state) {
state.counter++
}
}
export const actions = {
async nuxtServerInit({ state, commit }, { req }) {
const cookies = this.$cookies.getAll()
...
}
这是它的样子,非常简单。
文件夹结构
store
┣ auth
┣ utils
┣ posts
┃ ┗ actions.js
┃ ┗ mutations.js
┃ ┗ getters.js
┃ ┗ index.js
┣ index.js
例子
store/posts/index.js
你可以只放状态函数。您不需要导入动作、吸气剂和突变。
export const state = () => ({
comments: []
})
store/posts/actions.js
const actions = {
async getPosts({ commit, state }, obj) {
return new Promise((resolve, reject) => {
...
}
}
}
export default actions
store/posts/mutations.js
const mutations = {
CLEAR_POST_IMAGE_CONTENT: (state) => {
state.post_image_content = []
}
}
export default mutations
store/posts/getters.js
const getters = {
datatest: (state) => state.datatest,
headlineFeatures: (state) => state.headlineFeatures,
}
export default getters
效果与@CMarzin 的回答相同,但更清晰