vue2--Vuex 模块化

Vuex 模块化(modules)

├─ 1. 为什么要分模块?

│ └─ 项目变大后,把所有状态写在一起会很难维护,所以拆成多个小模块,

│ 每个模块管自己那一块数据(比如 user 管用户,setting 管设置)。

├─ 2. 怎么定义一个模块?

│ ├─ 新建一个 .js 文件(例如 user.js / setting.js)

│ ├─ 里面写 state、mutations、actions、getters

│ └─ 最重要的一点:如果要让模块"独立",必须加上 namespaced: true

│ (开启命名空间,后面会反复用到)

├─ 3. 怎么注册模块?

│ └─ 在 store/index.js 中:

import 模块 → 放到 new Vuex.Store({ modules: { ... } }) 里

├─ 4. 模块里的四样东西,怎么在组件中使用?

│ │

│ ├─ ① 访问 state(数据)

│ │ ├─ 直接写:$store.state.模块名.属性名

│ │ │ 例:$store.state.user.userInfo.name

│ │ └─ 用 mapState 辅助函数:

│ │ ...mapState('模块名', '属性名')

│ │ 需要模块开启 namespaced: true

│ │

│ ├─ ② 访问 getters(计算属性)

│ │ ├─ 直接写:$store.getters'模块名/getter名'

│ │ │ 例:$store.getters'user/UpperCaseName'

│ │ └─ 用 mapGetters 辅助函数:

│ │ ...mapGetters('模块名', 'getter名')

│ │ 需要模块开启 namespaced: true

│ │

│ ├─ ③ 调用 mutations(同步修改 state)

│ │ ├─ 直接写:$store.commit('模块名/方法名', 参数)

│ │ │ 例:$store.commit('user/setUser', newInfo)

│ │ └─ 用 mapMutations 辅助函数:

│ │ ...mapMutations('模块名', '方法名')

│ │ 需要模块开启 namespaced: true

│ │

│ └─ ④ 调用 actions(可以包含异步,再调用 mutation)

│ ├─ 直接写:$store.dispatch('模块名/方法名', 参数)

│ │ 例:$store.dispatch('user/setUserSecond', newInfo)

│ └─ 用 mapActions 辅助函数:

│ ...mapActions('模块名', '方法名')

│ 需要模块开启 namespaced: true

└─ 5. 几个关键规律(帮你记住)

├─ 规律1:state 天生挂在模块名下,不需要 namespaced 也能用 $store.state.模块名

├─ 规律2:getters、mutations、actions 默认会注册到全局,

│ 只有开启 namespaced: true 后,才必须加"模块名/"前缀来访问。

├─ 规律3:所有的 map 辅助函数(mapState、mapGetters...),

│ 只要想从某个模块里映射,第一个参数就是模块名,第二个参数是数组,

│ 前提都是 namespaced: true。

└─ 规律4:actions 里面的 context.commit('mutation名')

在开启命名空间后,会自动调用自己模块里的 mutation,不需要写模块名。

4.在模块里使用state,mutations,actions,getters

下面把第4部分 拆成4个具体的小例子,每个例子都会给出

  • 模块里的定义(user.js)

  • 组件里怎么"直接写"访问

  • 组件里怎么用"辅助函数"简化

所有例子都基于一个前提:模块必须开启 namespaced: true ,否则辅助函数没法直接用 '模块名' 来映射.

准备工作:模块定义(user.js)

javascript 复制代码
// store/modules/user.js
const state = {
  userInfo: {
    name: 'zs',
    age: 18
  }
}

const getters = {
  // 将用户名转为大写
  upperName(state) {
    return state.userInfo.name.toUpperCase()
  }
}

const mutations = {
  // 同步更新用户信息
  setUser(state, newInfo) {
    state.userInfo = newInfo
  }
}

const actions = {
  // 异步更新用户信息(1秒后更新)
  setUserAsync(context, newInfo) {
    setTimeout(() => {
      context.commit('setUser', newInfo)
    }, 1000)
  }
}

export default {
  namespaced: true, // 必须开启!
  state,
  getters,
  mutations,
  actions
}

① 访问 state(数据)

目标 :在组件中拿到 userInfo 这个对象

方式一:直接写

javascript 复制代码
<template>
  <div>
    <!-- 直接从 $store.state 里取 -->
    <p>用户名:{{ $store.state.user.userInfo.name }}</p>
    <p>年龄:{{ $store.state.user.userInfo.age }}</p>
  </div>
</template>

方式二:用 mapState 辅助函数

javascript 复制代码
<template>
  <div>
    <!-- 映射后可以直接用属性名 -->
    <p>用户名:{{ userInfo.name }}</p>
    <p>年龄:{{ userInfo.age }}</p>
  </div>
</template>

<script>
import { mapState } from 'vuex'

export default {
  computed: {
    // 把 user 模块里的 userInfo 映射成当前组件的计算属性
    ...mapState('user', ['userInfo'])
  }
}
</script>

② 访问 getters(计算属性)

目标 :在组件中拿到用户名的大写形式 upperName

方式一:直接写

注意写法:$store.getters['模块名/属性名'],这里用的是方括号,因为里面有斜杠。

javascript 复制代码
<template>
  <div>
    用户名大写:{{ $store.getters['user/upperName'] }}
  </div>
</template>

方式二:用 mapGetters 辅助函数

javascript 复制代码
<template>
  <div>
    用户名大写:{{ upperName }}
  </div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters('user', ['upperName'])
  }
}
</script>

③ 调用 mutations(同步修改 state)

目标 :通过点击按钮,把用户信息改成 { name: 'xiaowang', age: 25 }

方式一:直接写

javascript 复制代码
<template>
  <div>
    <button @click="changeUser">修改用户信息</button>
  </div>
</template>

<script>
export default {
  methods: {
    changeUser() {
      // 直接 commit,注意格式:'模块名/方法名'
      this.$store.commit('user/setUser', {
        name: 'xiaowang',
        age: 25
      })
    }
  }
}
</script>

方式二:用 mapMutations 辅助函数

点击按钮时,直接调用 this.setUser(参数) 即可,方法和参数都更简洁

javascript 复制代码
<template>
  <div>
    <button @click="setUser({ name: 'xiaowang', age: 25 })">
      修改用户信息
    </button>
  </div>
</template>

<script>
import { mapMutations } from 'vuex'

export default {
  methods: {
    // 把 user 模块里的 setUser 映射成本地方法
    ...mapMutations('user', ['setUser'])
  }
}
</script>

④ 调用 actions(异步操作,再调用 mutation)

目标:点击按钮后,延迟1秒再更新用户信息。

方式一:直接写

javascript 复制代码
<template>
  <div>
    <button @click="asyncChangeUser">异步修改用户信息</button>
  </div>
</template>

<script>
export default {
  methods: {
    asyncChangeUser() {
      this.$store.dispatch('user/setUserAsync', {
        name: 'xiaohong',
        age: 28
      })
    }
  }
}
</script>

方式二:用 mapActions 辅助函数

javascript 复制代码
<template>
  <div>
    <button @click="setUserAsync({ name: 'xiaohong', age: 28 })">
      异步修改用户信息
    </button>
  </div>
</template>

<script>
import { mapActions } from 'vuex'

export default {
  methods: {
    ...mapActions('user', ['setUserAsync'])
  }
}
</script>
要操作的 直接写法(模板/方法里写) 辅助函数映射(需要 namespaced: true)
state $store.state.user.xxx ...mapState('user', ['xxx'])
getters $store.getters['user/xxx'] ...mapGetters('user', ['xxx'])
mutation $store.commit('user/xxx', 参数) ...mapMutations('user', ['xxx'])
action $store.dispatch('user/xxx', 参数) ...mapActions('user', ['xxx'])

只要把这张表和上面的例子对着看,就会发现规律都是一样的:

"模块名" + "/" + "具体名称" ,然后辅助函数就是 ...mapXxx('模块名', [名称])

相关推荐
C++、Java和Python的菜鸟8 小时前
第5章 后端Web基础 (MySQL基础)
前端·mysql·adb
门前大桥下.8 小时前
HTML-01我的第一个网页
前端·html
浪客川8 小时前
Android的SystemUI的启动流程简析
android·开发语言
我是大卫8 小时前
【图】React源码解析-从数据结构、依赖追踪机制、值传播与更新触发、以及性能陷阱与优化,深挖useContext的底层原理
前端·react.js·源码
谭光志8 小时前
深入浅出 RAG:用一个可运行的 Demo 讲透完整链路
前端·后端·ai编程
Cobyte8 小时前
使用 JavaScript 实现有限状态机的经典问题
前端·javascript·vue.js
-银雾鸢尾-8 小时前
C#中的抽象类与抽象方法
开发语言·c#
道友可好9 小时前
前端工程师的 AI 时代生存指南
前端·人工智能·后端
●VON9 小时前
鸿蒙 PC Markdown 编辑器质量流水线:Web 构建、回归与 Release 门禁
前端·华为·编辑器·harmonyos·鸿蒙