深入理解Vuex 模块化(module)

yizhihongxing

深入理解Vuex 模块化(module)

背景介绍

Vue.js 是目前广泛应用于前端开发中的一款 JavaScript 框架。它的状态管理工具——Vuex, 大大减轻了开发者在组件之间共享数据时的繁琐操作,让数据流变得简单、易于维护、减少错误。那么如何更好地利用Vuex,使得你的代码更好的进行管理呢?这就需要深入理解Vuex模块化。

什么是Vuex 模块化(module)

在大型项目中,我们可以将 Vuex 的状态划分为多个模块。同一个模块可以有自己的 state、mutations、actions、getters等属性,同时这些属性也可以被其他模块访问,实现了模块化的效果。从而对于大型应用来说,这些模块组成一个完整的状态树,便于统一管理。

模块化开发的两种方式

Vuex 支持两种方式来进行模块化的开发:

方式一:直接使用模块内的属性的命名空间

命名空间是一个对象,该对象会与父模块的命名空间进行合并。这意味着,嵌套模块可以使用模块的全局命名空间,或者使用它们自己的本地命名空间。

const store = new Vuex.Store({
  modules: {
    account: {
      namespaced: true, // 开启命名空间
      state: {
        name: 'Tom',
        age: 18
      },
      mutations: {
        updateName(state, newName) {
          state.name = newName
        },
        updateAge(state, newAge) {
          state.age = newAge
        }
      },
      actions: {
        updateInfo({commit}, {name, age}) {
          return new Promise(resolve => {
            setTimeout(() => {
              commit('updateName', name)
              commit('updateAge', age)
              resolve()
            }, 1000)
          })
        }
      }
    }
  }
})

// 在组件使用时,在属性名称之前加上命名空间的名称
computed: {
  ...mapState({
    name: state => state.account.name,
    age: state => state.account.age
  })
},

methods: {
  ...mapActions('account', ['updateInfo'])
}

方式二:使用模块的嵌套属性来进行命名空间的操作

Vuex 还支持使用模块的嵌套属性来进行命名空间的操作。在这种模式下,我们可以使用命名空间的目录结构来查找模块的缩写。

// 定义子模块
const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  modules: { /* 子模块嵌套 */ }
}

// 定义 store
const store = new Vuex.Store({
  modules: {
    // 自动命名空间
    a: {
      state: { ... },
      mutations: { ... },
      actions: { ... },
      modules: {
        // 自动命名空间
        subModule: {
          state: { ... },
          mutations: { ... },
          actions: { ... }
        }
      }
    }
  }
})

// 在组件使用时,直接按照嵌套的层次调用属性即可
computed: {
  ...mapState({
    A: state => state.a.someProp,
    subA: state => state.a.subModule.someProp
  })
}

示例

示例一:嵌套模块

const store = new Vuex.Store({
  modules: {
    user: {
      namespaced: true, // 开启命名空间
      state: {
        name: 'Tom',
        age: 18
      },
      getters: {
        getName: state => state.name,
        getAge: state => state.age
      },
      mutations: {
        updateName(state, newName) {
          state.name = newName
        },
        updateAge(state, newAge) {
          state.age = newAge
        }
      },
      actions: {
        updateInfo({commit}, {name, age}) {
          return new Promise(resolve => {
            setTimeout(() => {
              commit('updateName', name)
              commit('updateAge', age)
              resolve()
            }, 1000)
          })
        }
      },
      modules: {
        info: {
          namespaced: true,
          state: {
            detail: 'This is the user information module.'
          },
          mutations: {
            updateDetail(state, newDetail) {
              state.detail = newDetail
            }
          },
          getters: {
            getDetail: state => state.detail
          }
        }
      }
    }
  }
})

// 在组件使用时,在属性名称之前加上命名空间的名称
computed: {
  ...mapState({
    name: state => state.user.name,
    age: state => state.user.age,
    detail: state => state.user.info.detail
  }),

  ...mapGetters('user', ['getName', 'getAge', 'info/getDetail'])
},

methods: {
  ...mapActions('user', ['updateInfo']),

  ...mapMutations('user', ['updateName', 'updateAge', 'info/updateDetail'])
}

示例二:分层模块

const store = new Vuex.Store({
  modules: {
    common: {
      namespaced: true,
      state: {
        loading: false,
        error: null
      },
      mutations: {
        showLoading(state) {
          state.loading = true
        },
        hideLoading(state) {
          state.loading = false
        },
        showError(state, error) {
          state.error = error
        },
        clearError(state) {
          state.error = null
        }
      },
      getters: {
        isLoading: state => state.loading,
        getError: state => state.error
      }
    },

    user: {
      namespaced: true,
      state: {
        name: 'Tom',
        age: 18
      },
      mutations: {
        updateName(state, newName) {
          state.name = newName
        },
        updateAge(state, newAge) {
          state.age = newAge
        }
      },
      actions: {
        fetchUserInfo({commit, dispatch}) {
          commit('common/showLoading', null, { root: true }); // 访问全局命名空间方法的方式

          return getUserInfo().then(res => {
            commit('updateName', res.name)
            commit('updateAge', res.age)
          },error => {
            commit('common/showError', error.message, { root: true });
            dispatch('reset', null, { root: true }); // 调用全局命名空间下的其他action
          }).finally(() => {
            commit('common/hideLoading', null, { root: true });
          })
        },
        reset({commit, dispatch}) {
          commit('updateName', 'Tom')
          commit('updateAge', 18)
          dispatch('common/clearError', null, { root: true }); // 调用全局命名空间下的其他mutation
        }
      }
    }
  }
})

// 在组件使用时,在属性名称之前加上命名空间的名称
computed: {
  ...mapState({
    name: state => state.user.name,
    age: state => state.user.age,
    isLoading: state => state.common.loading,
    error: state => state.common.error
  }),
  ...mapGetters('common', ['isLoading', 'getError'])
},

methods: {
  ...mapActions('user', ['fetchUserInfo', 'reset']),

  ...mapMutations('user', ['updateName', 'updateAge']),

  ...mapMutations('common', ['showLoading', 'hideLoading', 'showError', 'clearError'])
}

总结

通过以上示例,相信大家已经对Vuex的模块化有了深入了解。使用Vuex模块化,可以让我们的代码变得更加清晰易懂,分工更加明确,同时也更加方便地维护代码。在实际开发的过程中,可以结合实际业务需求,巧妙运用Vuex模块化进行状态管理,提高代码质量。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入理解Vuex 模块化(module) - Python技术站

(0)
上一篇 2023年5月28日
下一篇 2023年5月28日

相关文章

  • vue中methods、mounted等的使用方法解析

    对于这个问题,我会提供一个完整的攻略,包括以下内容: methods和mounted的基础用法 methods中使用箭头函数的注意事项 mounted中this的指向问题 示例说明 1. methods和mounted的基础用法 在Vue中,methods和mounted是两个非常常用的属性,分别用来定义组件的方法和生命周期函数。其中,methods用来定义…

    Vue 2023年5月28日
    00
  • Vue使用lodash进行防抖节流的实现

    下面是我对“Vue使用lodash进行防抖节流的实现”的完整攻略。 什么是防抖和节流 在讲解实现方法之前,我们来介绍一下什么是防抖和节流。 防抖指的是在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新开始计时。防抖常用于用户输入的场景中,如搜索框输入查询关键字。 节流指的是在一个时间段内只执行一次回调函数,即达到规定的执行间隔时间后才执行。常用于页…

    Vue 2023年5月29日
    00
  • vuecli4中如何配置打包使用相对路径

    首先,在 vuecli4 中使用相对路径来打包,需要在 vue.config.js 配置文件中进行相应的设置。可以按如下步骤进行设置: 步骤1:在项目根目录中创建 vue.config.js 文件。 module.exports = { // 其他配置 } 步骤2:在 exports 内添加 baseUrl 属性,并将其设置为相对路径。 module.exp…

    Vue 2023年5月28日
    00
  • Vue动态类的几种使用方法总结

    Vue动态类的几种使用方法总结 在Vue中,我们可以通过动态绑定class来实现根据条件来动态添加/删除对应的类,这也是实现复杂的样式变化的常用方式。本文将总结Vue中动态绑定class的几种使用方法,并提供相应的示例说明。 1. 对象语法 最基础的动态绑定class的方式是采用对象语法,其基本格式为: <div :class="{ clas…

    Vue 2023年5月28日
    00
  • vue,angular,avalon这三种MVVM框架优缺点

    下面是对vue、angular和avalon三种MVVM框架的详细讲解。 Vue 优点 渐进式框架,可以按需引入。 模块化开发,易于管理代码。 简化的模板语法,易于阅读和学习。 响应式数据绑定,可以实时更新视图。 Vuex 状态管理模式,方便管理全局状态。 社区活跃,有大量的第三方组件和插件可以选择。 缺点 学习曲线较陡峭。 不适合用来开发大型复杂的单页面应…

    Vue 2023年5月27日
    00
  • 如何用electron把vue项目打包为桌面应用exe文件

    下面是如何用electron把vue项目打包为桌面应用exe文件的完整攻略。 1. 安装electron 首先,需要在项目中安装electron。使用npm安装即可: npm install electron –save-dev 2. 修改package.json 接下来,在项目的package.json文件中添加以下内容: { "name&qu…

    Vue 2023年5月28日
    00
  • vue的图片需要用require的方式进行引入问题

    为了解释“Vue 的图片需要用 require 的方式进行引入问题”,首先需要对 Webpack 打包工具的处理方式进行简要说明。 Webpack 打包工具通过使用 ‘loader’(加载器)的引入不同类型的文件,包括图片、CSS文件等。其中图片文件处理经常出现的问题就是路径引入的方式。Webpack 打包工具提供了多种处理方式,其中包含使用require的…

    Vue 2023年5月27日
    00
  • 函数式组件劫持替代json封装element表格

    为了更好地解释“函数式组件劫持替代json封装element表格”的攻略,本次讲解分为以下几个步骤: 了解函数式组件 了解 Element 表格组件 劫持 Element 表格组件 在函数式组件中使用劫持的 Element 表格组件 示例演示 1. 了解函数式组件 函数式组件是 React 的一种组件类型,它是一个无状态的组件,只接收 props,返回一个 …

    Vue 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部