Vuex状态机的理解和使用

本文详细介绍了Vuex在Vue.js中的核心作用,包括状态抽取、单向数据流、安装方法、基础结构、模块化使用和严格的规则。通过实例演示了如何在项目中正确运用Vuex来管理共享状态和异步操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式

它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

以上是官方套话,详情直接看官网

1.对状态机vuex的理解

  1. 是一种状态管理模式,抽取共享状态
  2. 保证状态是可预测的变化
  3. 单向数据流

vuex
官 方 祖 传 的 单 向 数 据 流 图 。 官方祖传的单向数据流图。

2.安装

npm install vuex --save

3.vuex的基础结构

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  getters: {},
  modules: {}
})

在main.js中引入并挂载到实例上即可在组件中访问共享的状态:

import store from './store'
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

4.使用方法

挂载之后,在组件内访问方式如下:

  1. 访问共享状态
this.$store.state.STATE_NAME
  1. 提交状态变化
this.$store.commit(MUTATIONS_FUNC, PAYLOAD);
// 参数一:mutations中的提交修改state的方法名
// 参数二:载荷参数
  1. 异步处理并提交修改
this.$store.dispatch(ACTIONS_NAME, PAYLOAD);
// 参数一:actions 中的异步方法名
// 参数二:载荷参数

注:修改state绝对不可直接修改,如果直接修改就违背了***可预测***的特点,可以通过设置 strict: true,此时直接修改state会报错提示。

5.对基础结构的解释

  1. state

    管理所有共享的状态,同时状态存储是响应式的,所以在computed中返回state

  2. actions 异步方法,可返回Promise,也可使用语法糖

    actions中可以包含异步操作。

    不同于mutations,不可以直接commit。actions中提交的是mutation。

    由于actions中的函数提交的是mutations,所以actions的函数接收的参数就是上下store上下文,通过context.commit提交mutation。

    actions: {
      // async await语法糖,不扩展解释
        async add({ commit, dispatch, rootMutations }, payload) {
          commit('gotData', await getData())
        }
      }
    
  3. mutations 只能写同步方法,不可写异步方法!!

    唯一可以修改state的地方就是在mutation中进行修改。在mutation中接收state作为参数。在业务组件中通过commit调用指定的mutation,在调用的同时可以传递载荷参数,通常这个参数是对象(为了提交多个参数)。

    this.$store.commit(MUTATION_NAME, PAYLOAD);
    // 等同
    this.$store.commit({
      type: MUTATION_NAME,
      params1: VALUE,
      params2: VALUE
    })
    // 当使用对象形式提交的时候,整个对象都作为PAYLOAD提交到mutations的方法中
    

    vuex的state是响应式,所以mutation的使用也要和vue一样:

    1. 初始化所需的属性
    2. 新增删除属性需要使用Vue.set/Vue.delete保证属性的响应

    可以将mutations中的事件名称使用常量代替(非必须):使用常量的好处:不易出错,如果出错eslint会提示

    // mutation-types.js
    export const MUTATION_NAME = 'MUTATION_NAME';
    
    // store.js
    import Vuex from 'vuex'
    import { MUTATION_NAME } from './mutation-types'
    
    const store = new Vuex.Store({
      state: {},
      mutations: {
        [MUTATION_NAME] (state) {
          // todo
          // 注意:mutation中必须使用同步,不可使用异步,所有需要用异步处理的部分都需要在actions中
        }
      }
    })
    
  4. getters

    vuex可以在store中派生状态(getters也可以理解为store中的computed,拥有和computed一样的特性,返回值会被缓存)。

    // store.js
    import Vuex from 'vuex'
    import { MUTATION_NAME } from './mutation-types'
    
    const store = new Vuex.Store({
      state: {},
      getters: {
        GETTERS_NAME: state => {
          // todo
        }
      }
    })
    
    <!-- 组件内调用 -->
    <!-- 也可以根据实际情况传参 -->
    this.$store.getters.GETTERS_NAME
    
  5. modules

    为模块化服务,每个模块被模块化后通过modules引入。每个模块都有属于自己的以上的每一部分,包括modules。

    import Vue from 'vue'
    import Vuex from 'vuex'
    // 引入子模块的vuex
    import counter from "./counter";
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      // 模块化
      modules: {
        counter
      },
      // 使用严格模式
      strict: true
    })
    
    
    // module
    export default {
      // 设置独立的命名空间,避免命名冲突!!!!!!
      namespaced: true,
      state: {
        counter: 0
      },
      mutations: {
        // payload是传递进来的参数
        // 此处的state是module内部的state!!!!
        add(state, payload) {
          state.counter++;
          state.counter += payload;
        }
      },
      actions: {
        // 第一个参数是vuex上下文,state是通过上下文暴露出来的
        // payload是传递进来的参数{}
        // 此处时通过解构的形式
        add({ state, commit, dispatch, rootState }, payload) {
          return new Promise((resolve, reject) => {
            setTimeout(() => {
              commit('add', payload)
            }, 1000);
          });
        },
        // 在module的action中提交或者分发全局store中的mutation或action,那么就需要将{root: true},作为第三个参数传递给commit或dispatch!!!!!!!!!!!!!!
        someAction ({ dispatch, commit, getters, rootGetters }) {
          getters.someGetter // -> 'foo/someGetter'/局部
          rootGetters.someGetter // -> 'someGetter'/全局
    
          dispatch('someOtherAction') // -> 'foo/someOtherAction'/局部
          dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'/全局
    
          commit('someMutation') // -> 'foo/someMutation'
          commit('someMutation', null, { root: true }) // -> 'someMutation'
        },
      },
      getters: {
        // 此处的state是module内部的state!!!!
        // 直接讲rootState作为参数传递进来(如果有需要)
        doubleCounter(state, rootState) {
          // todo
        }
      }
    }
    

6.模块化以后的vuex如何使用

由于模块化开启了独立的命名空间,这就导致了访问指定的store需要加上命名空间。这就造成了不必要的麻烦。所以要使用vuex提供的辅助函数简化写法:

import { mapState, mapMutations, mapActions, mapGetters } from "vuex";

对于state:

@Component({
  components: {
    children1
  },
  computed: {
    // 通过扩展运算将需要的state,塞到computed中作为计算属性。
    // 数组内名称要和state中的状态名保持一致
    ...mapState(['PARAMS1','PARAMS2','PARAMS3']),
    params() {
      // 不影响自定义的计算属性
    }
  },
})

getters可以看作是store中的计算属性,进一步处理state,返回需要的值。对于getters:

@Component({
  components: {
    children1
  },
  computed: {
    // 数组内的名称要和store的getters中的名称保持一致
    ...mapGetters(['GETTERS_NAME1','GETTERS_NAME2']),
    params() {
      // 不影响自定义的计算属性
    }
  },
})

mutations中的方法相当于methods中的方法:

methods:{
  // 在需要的地方直接调用数组内的名称
 ...mapMutations(['MUTATIONS_NAME1', 'MUTATIONS_NAME2'])
}
// 等同于
methods:{
 	MUTATIONS_NAME1(payLoad){
  	this.$store.commit('MUTATIONS_NAME1',payLoad)
	},
  MUTATIONS_NAME2(payLoad){
  	this.$store.commit('MUTATIONS_NAME2',payLoad)
	}
}

actions中的方法类似mutation,区别在于 不可直接操作state 通过commit调用mutation去执行修改state。且为异步操作。

methods:{
  // 直接通过name去调用action,在action中执行commit动作,从而修改state
  ...mapActions(['ACTIONS_NAME1', 'ACTIONS_NAME2'])
  
  // 等同于
  ACTIONS_NAME1(){
    return this.$store.dispatch('ACTIONS_NAME1')
  }
}

如有不当之处,请指正。

keep learning

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小于___

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值