vuex 共享状态管理

1. 初始化 Vuex

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex) // 注册Vuex(Vue.use方法实际是调用了 Vuex 中的 install 方法)
const store = new Vuex.Store({
  /* 【1】全局共享的数据 */ 
  state: {}, 
  /* 【2】修改 state 中的数据(不能写异步) */ 
  mutations: {}, 
  /* 【3】处理异步(不能修改 state 中数据的值 只能在 mutations 中修改) */ 
  actions: {}, 
  /* 【4】getter(和计算属性的功能差不多) */ 
  getters: {},
  /* 【5】模块化数据 */
  modules: {}
})
new Vue({
  el: '#app',
  store
})

2. Vuex 新特性

2.1 Vuex 中 state 特性

  • state 作用:共享数据的定义

    state: { count:0 }
    
  • .vue 文件中使用

    // 方法一
    this.$store.state.count 
    
    // 方法二(辅助函数)
    import { mapState } from 'vuex' 
    computed:{ 
      ...mapState(['count']) 
    }
    // 使用
    this.count
    

2.2 Vuex 中 mutations 特性

  • mutations 作用:修改 state 中数据(不能写异步方法,异步方法在actions中写)

    mutations: {
      // 参数1:state 为共享数据
      // 参数2:payload 为载荷参数
      setCount(state, payload){
        state.count += payload
      }
    }
    
  • .vue 文件中使用

    // 方法一
    this.$store.commit(mutations中修改state中数据方法, 载荷参数)
    this.$store.commit('setCount', 2)
    
    // 方法二(辅助函数)
    import { mapMutations } from 'vuex'
    methods: {
      ...mapMutations(['setCount'])
    }
    // 调用 mutations 中方法
    this.setCount(2) 
    

2.3 Vuex 中 actions 特性

  • actions 作用:mutations中方法只能同步处理数据,不能写异步方法,actions中可以写异步方法

    actions: {
      // 参数1:context 执行的上下文对象(相当于组件中 this.$store store 的运行实例)
      // 参数2:payload 为载荷参数
      getCount(context, payload) {
        // 定时器中函数为异步函数
        setTimeout(() => {
          context.commit('setCount', payload)
        }, 1000)
        // 或接口请求获取数据 - 异步
      }
    }
    
  • 【注意】actions 中方法不能修改数据,通过调用 mutations 修改数据

  • .vue 文件中使用

    // 方法一
    this.$store.dispath(actions中异步方法名称, 载荷参数)
    this.$store.dispath('getCount', 2)
    
    // 方法二(辅助函数)
    import { mapActions } from 'vuex'
    methods: {
      ...mapActions(['getCount'])
    }
    // 调用该异步方法
    this.getCount(2) // 调用 actions 中方法
    

2.4 Vuex 中 getters 特性

  • getters 作用:包装处理(可以说是 vuex 中计算属性)

    state: {
      list: [12,2,56,1,545,12,23,5,98],
      count: 0
    },
    getters: {
      showCount: (state) => state.count,
      showList: (state) => state.list.filter(item => item % 2 === 0 })
    }
    
  • .vue 文件中使用

    // 方法一
    this.$store.getters.count
    
    // 方法二(辅助函数)
    import { mapGetters } from 'vuex'
    computed: {
      ...mapGetters(['showCount', 'showList'])
    }
    // 使用
    this.showCount
    this.showList
    

2.5 Vuex 中 modules 特性(模块化)

  • modules 作用:避免共享数据太多,全部在一个对象中,造成代码臃肿,维护性差

    modules: {
      /**** 定义模块:可以定义多个模块,每个模块中都有 state、mutations、actions、getters ****/
      // 【模块1】(modules1 模块名自命名)
      modules1: {
        state: {
          count: 10
        },
        mutations: {
          setData(state) {……}
        },
        actions: {
          // context: 有属性 state、commit、rootState
          setData(context) {……}
        },
        getters: {
          // rootState 根节点状态
          count: (state, getters, rootState) => state.count
        }
      },
      // 【模块2】
      modules2: {
        nameSpaced: true, // 命名空间(模块拥有高度封闭性)
        state: {
          number: 20
        },
        mutations: {},
        actions: {},
        getters: {}
      }
    }
    

    【注意】

    1. 模块的局部状态,对于模块内部的 mutationgetter ,接收的第一个参数是模块的局部状态对象
    2. 对于模块内部的 action, 局部状态通过 context.state 暴露出来,根节点状态则为context.rootState
    3. 对于模块内部的 getter , 根节点状态会作为第三个参数暴露出来
  • .vue 文件中使用

    /* 【方法一】 */
    this.$router.state.模块名称.state中属性名 
    // 【注意】模块名称后不用再写state,直接写state中属性即可
    this.$router.state.modules1.state.count // ×
    this.$router.state.modules1.count // √
    this.$router.state.modules2.number
    
    /* 【方法二】(辅助函数) */
    // 1.在 store 的 js 文件中根级别 getters 中获取模块化的数据
    const store = new Vuex.Store({
      state: {}, 
      mutations: {}, 
      actions: {}, 
      getters: {
        showModulesCount: () => state.modules1.count,
        showModulesNumber: () => state.modules2.number
      },
      modules: {
        …… // 模块化代码(见上)
      }
    })
    // 2.借助 mapGetters 取模块化中数据
    import { mapGetters } from 'vuex'
    computed: {
      ...mapGetters(['showModulesCount', 'showModulesNumber'])
    }
    // 3.使用该 getters 数据
    this.showModulesCount
    this.showModulesNumber
    

2.6 Vuex 中模块化命名空间 nameSpaced

  • 命名空间由来

    默认情况:模块内部的 mutation 、action 和 getter 是注册在 全局命名空间 的,这样使得多个模块能够对同一 mutation 或 action 作出响应。

    /******** 代码演示说明 ********/
    // 模块
    modules: {
      modules1: {
        state: {
          count: 10
        },
        mutations: {
          updateData(state) {……}
        }
      }
    }
    
    // 调用模块中修改 state 中数据的方法
    import { mapMutations } from 'Vuex'
    methods: {
      ...mapMutations(['updateData'])
    }
    // 使用方法
    this.$store.commit('updateData')
    // 【总结】和不用模块化时调用没有什么不同(方法在子模块中,但仍可以通过调用全局方法的方式调用)
    

    想要:保证内部模块的高封闭性,可以使用 nameSpaced: true 进行设置,使当前模块变为带有命名空间的模块。

  • 命名空间书写位置:

    模块名称对象中直接属性 nameSpaced (具体见 2.5 模块2 modules2 中 nameSpaced 书写位置)

拥有命名空间的模块中 mutations、actions、getters 调用

  1. 命名空间模块中 mutations 在 .vue 文件中使用

    【区别】其实就是加上模块路径

    // 模块代码
    modules: {
      modules1: {
        nameSpaced: true, // 【重点】开启命名空间
        state: {
          count: 10
        },
        mutations: {
          updateData(state) {……}
        },
        actions: {
          updateDataAx(context) {……}
        },
        getters: {
          showCount: (state) => state.count
        },
      }
    }
    
    • .vue 文件中使用
    /* 【方法一】 */
    this.$store.commit('模块名称/调用的mutations中方法名')
    this.$store.commit('modules1/updateData')
    
    /* 【方法二】借用辅助函数 mapMutations */
    import { mapMutations } from 'Vuex'
    methods: {
      ...mapMutations(['模块名称/mutations中方法名'])
      ...mapMutations(['modules1/updateData'])
    }
    // 调用该方法
    this.modules1/updateData() // × 该写法不不符合规定
    this['modules1/updateData']() // √ 
    
    /* 【方法三】借用辅助函数:创建基于某个命名空间的函数 */
    import { createNamespacedHelpers } from 'vuex'
    const { 对应当前模块名称中的 mapMutations } = createNamespacedHelpers('模块名称')
    const { mapMutations } = createNamespacedHelpers('modules1')
    methods: {
      ...mapMutations(['mutations中方法名'])
      ...mapMutations(['updateData']) // 此处的 mapMutations 为 modules1 中的mapMutations
    }
    // 调用该方法
    this.updateData()
    

    【注意】模块不加命名空间时 -> 方法三不可用

  2. 此处省略 - 命名空间模块中 actionsgetters 在 .vue 文件中使用

  3. 命名空间模块中 mutations actionsgetters 在 .vue 文件中使用完整代码

    /**** store 的js文件中 modules 中模块化代码 ****/
    modules: {
    	// 模块名称: modulesName
      modulesName: {
        namespaced: true, // 开启模块命名空间
        state: {
          count: 0,
          num: 1,
        },
        mutations: {
          updateCount(state, payload) {
            state.count += payload
          },
          updateCount_copy(state, payload) {
            state.count += payload
          },
        },
        actions: {
          updateCountAx(context, payload) {
            setInterval(() => {
              context.commit('updateCount', payload)
            }, 2000)
          },
          updateCountAx_copy(context, payload) {
            setInterval(() => {
              context.commit('updateCount_copy', payload)
            }, 2000)
          },
        },
        getters: {
          showCount: (state) => state.count,
          showNum: (state) => state.num,
        },
      },
    },
    
    <!-- .vue 文件中使用 -->
    <template>
      <div>
        count值:{{ $store.state.modulesName.count }} 
        getters中 count:{{ this["modulesName/showCount"] }}
        getters中 num:{{ showNum }}
        <br />
        <button @click="clickPri">点击(原始方法)</button>
        <button @click="clickMap">点击(mapMutations)</button>
        <button @click="clickCreate">点击(createNamespacedHelpers)</button>
      </div>
    </template>
    
    <script>
    import {
      mapMutations,
      mapActions,
      mapGetters,
      createNamespacedHelpers,
    } from "vuex";
    const {
      mapMutations: mapMutationsHelper,
      mapActions: mapActionsHelper,
      mapGetters: mapGettersHelper,
    } = createNamespacedHelpers("modulesName");
    
    export default {
      computed: {
        ...mapGetters(["modulesName/showCount"]),
        ...mapGettersHelper(["showNum"]),
      },
      methods: {
        ...mapMutations(["modulesName/updateCount"]),
        ...mapActions(["modulesName/updateCountAx"]),
        ...mapMutationsHelper(["updateCount_copy"]),
        ...mapActionsHelper(["updateCountAx_copy"]),
        // 【方法一】原始方法
        clickPri() {
          this.$store.commit("modulesName/updateCount", 1);
        },
        // 【方法二】借助 mapMutations 辅助函数 
        clickMap() {
          this["modulesName/updateCount"](2);
        },
        // 【方法三】借助 createNamespacedHelpers 辅助函数,创建基于某个命名空间的函数
        clickCreate() {
          this.updateCount_copy(3);
        },
      },
    };
    </script>
    

模块化第三个参数 {root: true}
commit({
type:‘方法名’,
载荷})

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值