🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] >[success] # mutation 与 action / module ![](https://img.kancloud.cn/b3/f9/b3f994c71d894b582bae15b4a1df8ebb_701x551.png) 上图是 **Vuex** 状态管理的 **流程**,描述了从 **Vue Components(组件)** 执行 **异步操作** 的一个 **环形流程** ,实际上如果 **没有异步操作的需求** 就不用走 **Actions** 的这个步骤, **2种操作(同步、异步操作)** 的流程如下: 1. **异步操作**: **Vue Components(组件)** > **Actions(请求接口操作写这里)** > **Mutations(接口成功返回值后在这里修改State的值)** > **State状态更新** > **Vue Components(组件)视图更新** 2. **同步操作** : **Vue Components(组件)** > **Mutations(修改State的值)** > **State状态更新** > **Vue Components(组件)视图更新** >[success] ## mutation 我们想修改 **State** 时,**不可以直接修改(例如:this.$store.state.appName = '小阿giao') state** ,而是要通过一个 **Commit** 提交一个 **Mutations** ,或者 **Dispatch** 一个 **Actions** 来走上图( **Vuex状态管理的流程图** )这个 **环形流程** 来修改 **State** 1. 首先在 **store文件夹** 中 创建一个 **mutations.js** **store/mutations.js** ~~~ const mutations = { // } export default mutations ~~~ 2. 在 **store/index.js** 中引入 **mutations.js** **store/index.js** ~~~ import Vue from 'vue' import Vuex from 'vuex' import state from './state' // state.js文件可以不写.js结尾,这样写也会自动找到state.js文件 import getters from './getters' import mutations from './mutations' import actions from './actions' import user from './module/user' // 引入模块文件 Vue.use(Vuex) export default new Vuex.Store({ state, // ES6对象简写的形式,state: state 等同与 state getters, mutations, actions, modules: { // 模块引用 user } }) ~~~ >[success] ### 使用方法 上面把 **根状态** 的 **mutations** 引入完成了, 那么如何通过 **mutations** 来修改 **state** 呢,首先 **展示一个错误的修改方式** >[success] #### 错误方式 **sotre.vue** ~~~ <template> <div> <p>{{ appName }}</p> <button @click="handleChangeAppName">修改appName</button> </div> </template> <script> export default { computed:{ appName(){ return this.$store.state.appName } }, methods:{ handleChangeAppName(){ // 不可以通过这种方式来修改state中的appName this.appName = 'newAppName' } } } </script> ~~~ 我在上面的 **store.vue** 文件中通过 **点击事件** 直接 **修改计算属性** ,这时浏览器会报错 ![](https://img.kancloud.cn/39/d9/39d9650e563c32a17c2039ecc194ddb1_549x118.png) 意思是 **【计算属性】 被注册,但是它没有 【setter方法】**,大白话就是 **【一个计算属性】,默认情况下只有一个【getter方法】,没有【setter方法】。** **getter方法触发方式** :**计算属性** 被 **读取** 时,**getter方法** 会被触发。 **setter方法触发方式** :**修改计算属性** 的时候,会触发 **setter方法** 。 下面的代码进行了 **错误的示范** 修改了 **计算属性**: **store.vue** ~~~ <template> <div> <p>{{ nameB }}</p> <button @click="handleChangeNameB">修改计算属性nameB</button> </div> </template> <script> export default { data(){ return{ name: '路飞' } }, computed:{ nameB: { set: function(newValue){ // nameB被修改时,该函数会被触发。这里可以当做watch或者change来使用 this.name = `${ newValue }真是奥利给` }, get: function(newValue){ // 处理过后的值,返回(return)给使用nameB的地方 return this.name + '索隆' } } }, methods:{ handleChangeNameB(){ this.nameB = '娜美桑' } } } </script> ~~~ >[success] #### 正确方式 1. 使用 **commit** 调用 **mutations** 中的方法来修改 **state** 首先在 **store/state.js** 中设置 **appName全局变量** **store/state.js** ~~~ const state = { appName: 'admin' } export default state ~~~ 然后在 **store/mutations.js** 中写上 **修改 state 的方法** **store/mutations.js** ~~~ const mutations = { /** * 修改app名称方法 * @param state 【state】指的是同级的【state】,也就是【根级别】的中的state * @param params 调用SET_APP_NAME方法时传过来的参数,可以传基本数据类型(字符串、布尔等),也可以传入引用类型(对象、数组、等) */ SET_APP_NAME(state, params){ state.appName = params } } export default mutations ~~~ 在使用到文件中这样使用即可 **store.vue** ~~~ <template> <div> <p>{{ appName }}</p> <button @click="handleChangeAppName">修改Vuex中的appName</button> </div> </template> <script> export default { computed:{ appName: function(){ return this.$store.state.appName } }, methods:{ handleChangeAppName(){ // commit第一个参数为mutations中方法名,第二个参数为要传过去的值 this.$store.commit('SET_APP_NAME', 'newAppName') } } } </script> ~~~ 或者 **commit** 也可以传 **一个参数** , **传个对象** ,如下: **store.vue** ~~~ <template> <div> <p>{{ appName }}</p> <button @click="handleChangeAppName">修改Vuex中的appName</button> </div> </template> <script> export default { computed:{ appName: function(){ return this.$store.state.appName } }, methods:{ handleChangeAppName(){ this.$store.commit({ type: 'SET_APP_NAME', // type就是要执行mutations里的方法的名称 appName: 'newAppName' // 这里appName可以对应state要修改的state }) } } } </script> ~~~ **store/mutations.js** ~~~ const mutations = { /** * 修改app名称方法 * @param state 【state】指的是同级的【state】,也就是【根级别】的中的state * @param params 调用SET_APP_NAME方法时传过来的参数,可以传基本数据类型(字符串、布尔等),也可以传入引用类型(对象、数组、等) */ SET_APP_NAME(state, params){ state.appName = params.appName } } export default mutations ~~~ 2. 使用 **Vue** 的 **Set 动态添加State** 假如 **state 中有一个变量以后要使用** ,但是 **现在 state 中是没有声明定义这个变量** ,就需要用到 **Vue** 提供的 **Set** 方法来添加 **State**,因为在 **最初state 中 没有声明定义这个变量** ,然后通过的 **mutation** 来 **修改这个变量** 是 **不会触发视图更新** 的 ,因为 **最初没有在实例上定义声明的变量是没有get跟set方法的**,所以**不会触发视图更新**,如果想 **触发视图更新** 只有通过 **Vue** 提供的 **Set** 方法来向 **State** 中 **添加变量**,同时也会给这个 **变量** 添加 **get** 跟 **set** 方法,以达到 **视图更新** 的效果,案例如下: 假如我以后在 **store/state.js** 中有一个 **appVersion** 的变量以后要用到,但是目前没有在 **state** 中 **定义声明** **store/state.js** ~~~ const state = { appName: 'admin', // appVersion: '1.0' } export default state ~~~ 在 **store/mutations.js** 中写 **动态添加appVersion** 变量的方法,主要是用到了 **Vue** 的 **Set** 方法,来做到动态添加 **State** **store/mutations.js** ~~~ import vue from 'vue' const mutations = { SET_APP_VERSION(state, params){ vue.set(state, 'appVersion', params.appVersion) // vue的$set方法动态向state中添加appVersion } } export default mutations ~~~ 在 **页面中使用** 这样写 **store.vue** ~~~ <template> <div> <p>版本号{{ appVersion }}</p> <button @click="handleChangeAppVersion">向Vuex中添加appVersion</button> </div> </template> <script> export default { computed:{ appVersion: function(){ return this.$store.state.appVersion } }, methods:{ // 点击按钮添加app版本号(appVersion) handleChangeAppVersion(){ this.$store.commit({ type: 'SET_APP_VERSION', appVersion: '1.0' }) } } } </script> ~~~ 3. **mapMutations方法快速访问 mutation 中的函数** 上面描述了通过 **commit** 方法执行一个 **mutation** 中定义的 **函数** 来修改 **state** ,以及使用 **Vue** 提供的 **Set** 方法动态向 **state** 中 **添加变量** ,接下来讲一下如何使用 **Vuex** 提供的 **mapMutations** 方法来调用 **mutation** 中的方法。 ***** 3.1 **使用 mapMutations 访问 【根状态】 以及 【module(模块)】中的 【mutation】** 首先 **store.vue** 文件中引入 **mapMutations** ,然后再通过 **...mapMutations([ 'mutation中定义的方法名称' ])** 把 **Vuex** 中的 **mutation** 中的方法(这里 **mapMutations方法** 中的 **数组参数** ,无论是 **根状态(store/index.js)** 下,还是 **module(模块)** 下的 **mutation** 方法,都可以通过 **mapMutations** 方法引入),引入到 **methods** 中 **store.vue** ~~~ <template> <div> <p>用户名:{{ userName }}</p> <p>app名称:{{ appName }}</p> <button @click="handleChangeAppName">修改app名称</button> <button @click="handleChangeUserName">修改用户名</button> </div> </template> <script> import { mapMutations } from 'vuex' export default { computed:{ appName: function(){ // 根状态下的state return this.$store.state.appName }, userName: function(){ // module(模块)下的state return this.$store.state.user.userName } }, methods:{ ...mapMutations([ // 1. 通过(扩展运算符)...mapMutations来把Vuex中mutation的方法展开到methods中 'SET_APP_NAME', 'SET_USER_NAME' ]), handleChangeAppName(){ // 2. 调用根状态下mutation中的SET_APP_NAME方法 this.SET_APP_NAME('看云app') }, handleChangeUserName(){ // 2. 调用module(模块)中mutation中的SET_USER_NAME方法 this.SET_USER_NAME('小黑') } } } </script> ~~~ **根状态** 的 **store/mutations.js** **store/mutations.js** ~~~ const mutations = { /** * 修改app名称方法 * @param state 【state】指的是同级的【state】,也就是【根级别】的中的state * @param params 调用SET_APP_NAME方法时传过来的参数,可以传基本数据类型(字符串、布尔等),也可以传入引用类型(对象、数组、等) */ SET_APP_NAME(state, params){ state.appName = params } } export default mutations ~~~ **根状态** 的 **store/state.js** **store/state.js** ~~~ const state = { appName: '腾讯qq', } export default state ~~~ **module(模块)的 js 文件** **store/module/user.js** ~~~ const state = { userName: '小明' } const mutations = { SET_USER_NAME(state, params){ state.userName = params } } const actions = { // } const getters = { firstLetter: (state) => { // 定义getter return state.userName.substr(0, 1) } } export default { // namespaced: true, // 注意这里没有开启命名空间 getters, state, mutations, actions } ~~~ 3.2 **mapMutations配合命名空间使用** **store/module/user.js** ~~~ const state = { userName: '小明' } const mutations = { SET_USER_NAME(state, params){ state.userName = params } } const actions = { // } const getters = { firstLetter: (state) => { // 定义getter return state.userName.substr(0, 1) } } export default { namespaced: true, // 开启命名空间 getters, state, mutations, actions } ~~~ **store.vue** ~~~ <template> <div> <p>用户名:{{ userName }}</p> <button @click="handleChangeUserName">修改用户名</button> </div> </template> <script> import { mapMutations } from 'vuex' export default { computed:{ userName: function(){ // module(模块)下的state return this.$store.state.user.userName } }, methods:{ ...mapMutations('user',[ // 1. 第一个参数module(模块)名称,第二个参数模块中的mutations里的方法名 'SET_USER_NAME' ]), handleChangeUserName(){ // 2. 调用module(模块)中mutation中的SET_USER_NAME方法 this.SET_USER_NAME('小黑') } } } </script> ~~~ 或者可以使用**mapMutations**配合**Vuex**提供的**createNamespacedHelpers**方法一起使用来获取**模块**中的**mutations**,这种方式 **mapMutations 不需要写第一个模块名的参数** ~~~ <template> <div> <p>用户名:{{ userName }}</p> <button @click="handleChangeUserName">修改用户名</button> </div> </template> <script> import { createNamespacedHelpers } from 'vuex' const { mapMutations } = createNamespacedHelpers('user') // createNamespacedHelpers('模块名称') export default { computed:{ userName: function(){ // module(模块)下的state return this.$store.state.user.userName } }, methods:{ ...mapMutations([ // 1. 上面使用了createNamespacedHelpers,这里就不用像之前一样再写模块名作为第一个参数 'SET_USER_NAME' ]), handleChangeUserName(){ // 2. 调用module(模块)中mutation中的SET_USER_NAME方法 this.SET_USER_NAME('小黑') } } } </script> ~~~ >[success] ## action 我们想进行一些 **异步操作(请求接口)** 后想修改 **state** ,就要在 **action** 中写 **异步操作(请求接口)**,然后执行 **commit** 方法提交一个 **mutation** ,再在 **mutation** 中修改 **state** 。 1. 首先在**store文件夹**中 创建一个**actions.js** **store/actions.js** ~~~ const actions = { /** * 通过接口更新app名称方法 * @param { commit } 【commit】是一个方法,调用它可以提交一个【mutation】的方法,通过【mutation】来修改【state】 * @param */ updateAppName({ commit }){ // } // 上面的写法是ES6的结构赋值的写法,相当于下面这样写: // updateAppName(paramsObj){ // const commit = paramsObj.commit // } } export default actions ~~~ 2. 在 **store/index.js** 中引入**actions.js** **store/index.js** ~~~ import Vue from 'vue' import Vuex from 'vuex' import state from './state' // state.js文件可以不写.js结尾,这样写也会自动找到state.js文件 import getters from './getters' import mutations from './mutations' import actions from './actions' import user from './module/user' // 引入模块文件 Vue.use(Vuex) export default new Vuex.Store({ state, // ES6对象简写的形式,state: state 等同与 state getters, mutations, actions, modules: { // 模块引用 user } }) ~~~ >[success] ### 使用方法 **需求** :根据调用接口返回 **appName**,并且赋值给 **state** 中定义好的 **appName** 。 1. 使用 **mapActions** 方法来把 **action** 的 **异步方法** 引入到 **methods** 中使用。这种方法无论是 **根状态** 的 **action** ,还是 **module** 的 **action** 都可以使用 **mapActions** 进行引入。 首先在 **actions.js** 中写好 **异步操作** 的方法, **updateAppName** 方法,并且在 **updateAppName** 方法中调用了 **src/api/app.js** 中的 **getAppName接口** **store/actions.js** ~~~ import { getAppName } from '@/api/app' // 前面的是简写,等同于@/api/app.js const actions = { /** * 通过接口更新app名称方法 * @param { commit } 【commit】是一个方法,调用它可以提交一个【mutation】的方法,通过【mutation】来修改【state】 */ updateAppName({ commit }){ getAppName().then(res => { // 解构赋值来取appName const { info: { appName } } = res commit('SET_APP_NAME', appName) }).catch(err => { console.log(err) }) } } export default actions ~~~ 下面是一个 **模拟的接口** , **如果成功就返回成功的数据,如果失败就返回错误** 。 **src/api/app.js** ~~~ /** * 获取app名称接口 */ export const getAppName = () => { return new Promise((resolve, reject) => { const err = null setTimeout(() => { if(!err) resolve({ code: 200, info: { appName: 'newAppName' } }) else reject(err) }) }) } ~~~ 在上面的 **store/actions.js** 中的 **updateAppName** 方法调用后,执行了 **src/api/app.js** 中的 **getAppName** 接口,接口成功后通过 **commit** 执行了一个 **mutation** 方法,并且在 **mutation** 方法中修改了 **state** 中的 **appName** ,如下: **store/mutations.js** ~~~ const mutations = { /** * 修改app名称方法 * @param state 【state】指的是同级的【state】,也就是【根级别】的中的state * @param params 调用SET_APP_NAME方法时传过来的参数,可以传基本数据类型(字符串、布尔等),也可以传入引用类型(对象、数组、等) */ SET_APP_NAME(state, params){ state.appName = params } } export default mutations ~~~ 还有 **state.js** , **默认是空字符串** **store/state.js** ~~~ const state = { appName: '', } export default state ~~~ 最终在使用 **action** 的 **store.vue组件** 中通过 **mapActions** 将 **action** 中异步的方法引入到 **methods** 中,通过点击 **【获取app名称】** 按钮来执行 **action** 中的 **updateAppName** 异步方法,来通过接口来 **获取app名称** 。 **store.vue** ~~~ <template> <div> <p>app名称:{{ appName }}</p> <button @click="handleChangeAppName">获取app名称</button> </div> </template> <script> import { mapActions } from 'vuex' export default { computed:{ appName: function(){ return this.$store.state.appName } }, methods:{ ...mapActions([ 'updateAppName' ]), handleChangeAppName(){ this.updateAppName() } } } </script> ~~~ 2. **mapActions** 配合 **命名空间** 使用 在 **module** 中开启 **命名空间** 把 **namespaced:true** **store/module/user.js** ~~~ const state = { userName: '小明' } const mutations = { SET_USER_NAME(state, params){ state.userName = params } } const actions = { updateUserName({ commit }){ // 这里假装是执行完成接口后,执行commit commit('SET_USER_NAME','小黑') } } const getters = { firstLetter: (state) => { // 定义getter return state.userName.substr(0, 1) } } export default { namespaced: true, // 开启命名空间 getters, state, mutations, actions } ~~~ 然后组件中给 **mapActions** 添加 **第一个参数** ,**第一个参数为模块名称** 。 **store.vue** ~~~ <template> <div> <p>{{ userName }}</p> <button @click="handleChangeUserName">获取用户名称</button> </div> </template> <script> import { mapActions } from 'vuex' export default { computed:{ userName: function(){ return this.$store.state.user.userName } }, methods:{ ...mapActions('user',[ 'updateUserName' ]), handleChangeUserName(){ this.updateUserName() } } } </script> ~~~ 或者可以使用 **mapActions** 配合 **Vuex** 提供的 **createNamespacedHelpers** 方法一起使用来获取 **模块** 中的 **action**,这种方式 **mapActions 不需要写第一个参数** 。 ~~~ <template> <div> <p>{{ userName }}</p> <button @click="handleChangeUserName">获取用户名称</button> </div> </template> <script> import { createNamespacedHelpers } from 'vuex' const { mapActions } = createNamespacedHelpers('user') // createNamespacedHelpers('模块名称') export default { computed:{ userName: function(){ return this.$store.state.user.userName } }, methods:{ ...mapActions([ 'updateUserName' ]), handleChangeUserName(){ this.updateUserName() } } } </script> ~~~ 3. 使用 **dispatch** 来调用 **action** **store.vue** ~~~ <template> <div> <p>{{ userName }}</p> <button @click="handleChangeUserName">获取用户名称</button> </div> </template> <script> export default { computed:{ userName: function(){ return this.$store.state.user.userName } }, methods:{ handleChangeUserName(){ this.$store.dispatch('updateUserName', '我是params') } } } </script> ~~~ **store/module/user.js** ~~~ const state = { userName: '小明' } const mutations = { SET_USER_NAME(state, params){ state.userName = params } } const actions = { /** * 通过接口更新app名称方法 * @param { commit } 【commit】是一个方法,调用它可以提交一个【mutation】的方法,通过【mutation】来修改【state】 * @param params this.$store.dispatch('updateUserName', '我是params')时传的参数 */ updateUserName({ commit }, params){ console.log(params) // 我是params // 这里假装是执行完成接口后,执行commit commit('SET_USER_NAME','小黑') } } const getters = { firstLetter: (state) => { // 定义getter return state.userName.substr(0, 1) } } export default { getters, state, mutations, actions } ~~~ >[success] ### 补充 上面 **actions.js** 文件中在 **处理异步调用接口** 时使用了 **.then** 与 **.catch** ,这种是类似于 **回调的形式** ,看起来不是特别好,我们可以使用 **ES8** 的 **async** 、**await**,然后用 **try** 包裹成功要处理的数据,**catch** 处理失败,代码如下: **store/actions.js** ~~~ import { getAppName } from '@/api/app' // 前面的是简写,等同于@/api/app.js const actions = { /** * 通过接口更新app名称方法 * @param { commit } 【commit】是一个方法,调用它可以提交一个【mutation】的方法,通过【mutation】来修改【state】 */ // updateAppName({ commit }){ // getAppName().then(res => { // // 解构赋值来取appName // const { info: { appName } } = res // commit('SET_APP_NAME', appName) // }).catch(err => { // console.log(err) // }) // } // 用ES8后 async updateAppName({ commit }){ try{ const { info: { appName } } = await getAppName() commit('SET_APP_NAME', appName) } catch (err) { console.log(err) } } } export default actions ~~~ >[success] ## module 之前在创建项目时就已经把 **user** 拆分成了 **module(模块)** ,项目庞大时,**store** 变得非常臃肿,我们它们都拆分成 **module(模块)** ,这样专门管理起来比较 **清晰** , 每个 **module(模块)** 都是一个独立的 **store** ,所以在 **module(模块)** 中还可以包含 **module(模块)** ,如下: **store/module/user.js** ~~~ const state = {} const mutations = {} const actions = {} const getters = {} export default { getters, state, mutations, actions, modules: { // } } ~~~ 这样就可以在 **module模块** 中写 **module模块** 拆分出更细的 **模块** >[success] ### 命名空间 1. **module模块** 使用 **命名空间** 如果想给某个模块一个密闭的空间,防止其他地方污染到这个模块,就可以添加一个**namespaced: true**即可变成为**命名空间**,如下: **store/module/user.js** ~~~ const state = { userName: '小明' } const mutations = { SET_USER_NAME(state, params){ state.userName = params } } const actions = { // } const getters = { firstLetter: (state) => { // 定义getter return state.userName.substr(0, 1) } } export default { namespaced: true, // 开启命名空间 getters, state, mutations, actions } ~~~ **module(模块)** 中使用了 **命名空间**, 在 **组件中** 使用 **mapState** 、**mapGetters** 、**mapActions** 时就要在第一个参数上添加 **模块名称** **store.vue** ~~~ <template> <div> <p>用户名:{{ userName }}</p> <button @click="handleChangeUserName">修改用户名</button> </div> </template> <script> import { mapMutations } from 'vuex' export default { computed:{ userName: function(){ // module(模块)下的state return this.$store.state.user.userName } }, methods:{ ...mapMutations('user',[ // 1. 第一个参数module(模块)名称,第二个参数模块中的mutations里的方法名 'SET_USER_NAME' ]), handleChangeUserName(){ // 2. 调用module(模块)中mutation中的SET_USER_NAME方法 this.SET_USER_NAME('小黑') } } } </script> ~~~ 或者也可以使用 **Vuex** 提供的 **createNamespacedHelpers**方法来获取使用 **命名空间** 模块中的方法,上述代码中已经介绍到了 **createNamespacedHelpers** 如何使用,这里就不在再次陈述了。 2. **module(模块)中嵌套module(模块)模块** **module(模块)** 中嵌套 **module(模块)** 在 **组件中如何获取** 呢? **store.vue** ~~~ <template> <div> 获取模块中嵌套的模块中的方法 </div> </template> <script> import { mapMutations } from 'vuex' export default { methods:{ ...mapMutations('user/next',[ // 这样就能获取到模块中嵌套模块中的方法 'SET_USER_NAME' ]) } } </script> ~~~ >[success] ### 动态注册模块 1. **动态添加模块** 可以通过 **$store** 提供的 **registerModule** 方法来进行 **动态添加模块** 的操作 **store.vue** ~~~ <template> <div> <button @click="registerModule">动态注册模块</button> <p v-for="i in todoList" :key="i"> {{ i }} </p> </div> </template> <script> import { mapState } from 'vuex' export default { computed: { ...mapState({ // 这里需要判断,因为默认情况下是没有这个模块的,这个模块是动态添加进去的 todoList: state => state.todo ? state.todo.todoList : [] }) }, methods:{ registerModule(){ // 第一个参数:要新创建的模块名,第二个参数就是个对象,里面写我们的state,getter等等 this.$store.registerModule('todo', { state:{ todoList: [ '学习mutations', '学习actions' ] } }) } } } </script> ~~~ 2. **动态给某个模块添加模块(嵌套的模块)** ~~~ <template> <div> <button @click="registerModule">动态注册模块</button> <p v-for="i in todoList" :key="i"> {{ i }} </p> </div> </template> <script> import { mapState } from 'vuex' export default { computed: { ...mapState({ // 这里需要判断,因为默认情况下是没有这个模块的,这个模块是动态添加进去的 todoList: state => state.user.todo ? state.user.todo.todoList : [] }) }, methods:{ registerModule(){ // 第一个参数:要新创建的模块名,第二个参数就是个对象,里面写我们的state,getter等等 this.$store.registerModule(['user', 'todo'], { // 这里写成数组的形式代表给user模块添加一个todo子模块 state:{ todoList: [ '学习mutations', '学习actions' ] } }) } } } </script> ~~~ >[success] ### 补充 在 **module(模块)** 中使用 **action** 时,实际上除了 **commit参数** 外还有 **state参数(指向的是当前模块中的state)** 、 **rootState(指向的是store/index.js中的根状态中的state)、dispatch** ,如果想给某个模块一个密闭的空间,防止其他地方污染到这个模块,就可以添加一个 **namespaced: true** 即可变成为 **命名空间** ,代码如下: ~~~ const state = { // } const mutations = { // } const actions = { /** * 更新用户名称方法 * @param commit 执行一个mutation方法来修改state * @param state 当前模块中的state * @param rootState 根状态中的state * @param dispath 可以调用同级actions中的xxx方法,例如dispath(xxx, '') */ updateUserName({ commit, state, rootState, dispath }){ }, xxx(){ // } } export default { namespaced: true, // 开启命名空间 state, mutations, actions } ~~~ >[warning] ## 后期补充(该项后期删除) vuex页面刷新后状态消失,状态如何保存下来 以上的几种mapMutations以及之前的mapState 、mapGetter这几个都可以模块跟根部状态混合着写一起用吗