深入理解Vuex 模块化(module)

深入理解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中如何利用js函数截取时间的年月日时分秒

    在Vue中,利用JavaScript函数截取时间的年月日时分秒,可以使用内置的JavaScript Date对象。下面是Vue中如何利用js函数截取时间的年月日时分秒的完整攻略: 步骤1:获取当前时间 let today = new Date(); // 获取当前时间 console.log(today); // 打印当前时间 我们使用Date对象获取当前日…

    Vue 2023年5月29日
    00
  • Vue指令指令大全

    Vue指令是Vue.js的核心特性之一,为Vue.js提供了非常灵活和强大的操作DOM的能力。下面是Vue.js中常用的指令指令: v-text 指令格式:v-text 功能:用于在元素中输出文本内容,和插值表达式{{}}相同 示例: <!– Vue实例 –> <div id="app"> <p v-te…

    Vue 2023年5月27日
    00
  • webpack项目调试以及独立打包配置文件的方法

    下面是关于“webpack项目调试以及独立打包配置文件的方法”的完整攻略: 项目调试 方式一:使用devtool webpack的devtool选项用来配置source map的生成方式。设置这个选项可以很方便地进行调试。 常用的有以下几种: source-map:一种映射方式,会生成一个 .map 文件,会减慢打包速度。 cheap-module-sour…

    Vue 2023年5月28日
    00
  • vue项目如何实现前端预览word与pdf格式文件

    要实现前端预览word与pdf格式文件,我们需要借助一些第三方库或工具。以下是一些实现前端预览word与pdf格式文件的常见方法: 1. 使用第三方库进行预览 我们可以使用一些第三方库来实现前端预览word与pdf格式文件,例如viewerjs和pdf.js。 使用viewerjs Viewerjs是一个用于在网页上预览office文档和pdf文件的开源库。…

    Vue 2023年5月28日
    00
  • 详解VUE中的插值( Interpolation)语法

    下面是“详解VUE中的插值(Interpolation)语法”的攻略: 1. 什么是插值语法? 插值是一种模板引擎语法,用于将数据绑定到文本或属性中。在Vue中,插值语法可以用双大括号{{}}来表示,可以在HTML文本中任意使用。 例如,在Vue模板中,我们可以使用插值语法将data数据绑定到html标签中: <div> {{message}} …

    Vue 2023年5月27日
    00
  • VUE跨域详解以及常用解决跨域的方法

    VUE跨域详解以及常用解决跨域的方法 在前端开发过程中,我们经常遇到需要与不同的域名或端口的服务器进行数据交互的情况,这就会产生跨域问题。本文将详细讲解Vue中跨域的问题以及常用的解决方法。 什么是跨域 跨域是指,当一个网页的文档、脚本或资源请求另一个域名或端口的资源时,浏览器会对这个请求进行限制,以防止从一个域上的网页去攻击另一个域的网页。例如,一个使用h…

    Vue 2023年5月28日
    00
  • vue传值方式的十二种方法总结

    我来为你讲解一下“Vue传值方式的十二种方法总结”的完整攻略。 一、前言 在开发Vue的过程中,我们经常需要进行组件之间的数据传递。这时候,就需要选择一种合适的传值方式。本篇文章将为大家总结了十二种常见的Vue传值方式,并对它们进行详细的介绍和对比。希望对大家在开发中提供一些帮助。 二、直接传值 最简单的方式就是直接传值。也就是说,我们可以在父组件中直接将数…

    Vue 2023年5月27日
    00
  • 详解Vue生命周期的示例

    首先,我们需要了解Vue生命周期的概念。Vue实例有一个完整的生命周期,从开始创建、初始化数据、编译模板、挂载DOM、渲染、更新、销毁等一系列过程,我们称之为Vue的生命周期。 为了更全面地了解Vue生命周期,我们推荐先查看官方文档,并结合以下示例进行学习。 示例一:理解钩子函数的执行时机 Vue生命周期中有一些钩子函数,可以在不同阶段触发相关的行为,比如c…

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