Vue3第四篇之Vuex

1,155 阅读3分钟

Vuex

单向数据流的问题

  • 多个视图依赖同一个状态

  • 来自不同的视图的行为需要变更统一状态

----Vuex应运而生----

Vuex背后的思想:通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,把组件共享的状态抽离出来,以全局单例模式进行管理

image-20210712172008591

Actions:处理异步操作

Mutations:处理同步操作

上述两者都是为了使用devtools而创造的东西,为了方便开发者在开发过程中的调试,必须通过上述两种方式修改state才能在devtools中进行跟踪

一般在应用中进行统一状态管理的比如:

  • 用户的登录状态、用户名称、头像、地理位置信息等
  • 商品的收藏、购物车中的物品等

一、state

单一状态树,全局就一个

state = {
  key1: value1,
  key2: value2
}

在composition API中,获取state中的属性,如果要具有响应性,必须使用计算属性

//option API
computed: {
count(){
 return store.state.count
}
}
//composition API
let cnt = computed(() => store.state.count)

当一个组件需要获取多个状态的时候,将所有属性都声明为计算属性会比较麻烦,可以使用mapState函数映射来帮助我们获取计算属性

//其中userId和count为state中的属性
computed:{
    //简化数组写法,计算属性名称与state中的属性名相同才可以使用,访问的时候直接使用userId和count即可
    ...mapState(['userId', 'count']),
    //对象写法,访问的时候直接使用u1和u2即可
    ...mapState({u1:'userId', u2:'count'})
  },

二、getters

getters相当于是计算属性,可以含有两个参数,第一个是state,第二个是getters,如果想给他传入其他参数,需要返回一个函数,通过方法访问

//1个参数
getters: {
  powerCnt(state){
        return state.count*state.count;
    }
}

//2个参数
getters: {
  powerCnt2(state, getters){
        return getters.powerCnt+1;
    }
}

//通过getter返回一个函数,可以传参,即通过方法访问
getters: {
  powerCnt(state){
        return cnt => {
          cnt*4;
        }
    }
}
//调用的时候,使用store.getters.powerCnt(cnt)
store.getters.powerCnt(14)//14*4=56

这里也有mapGetters辅助函数,与mapState用法相同

三、mutation

修改Vuexstore中状态的唯一办法就是提交mutation(异步使用action),他类似于事件,每个mutation都有一个字符串的事件类型type和一个回调函数handler,这个回调函数就是我们实际进行状态更改的地方,mutation接受两个参数,一个是状态state,另一个是载荷payload

事件类型其实通俗的将等价于方法名,可以单独创建一个mutations-types.ts文件用来定义需要的事件类型,即使用创两替代mutation事件类型,如下:

export const SET_TOKEN = "setToken"
export const SET_USERID = "setUserId"
export const INCREMENT = "increment"
export const DECREMENT = "decrement"

载荷payload,一般情况是一个对象

具体使用,有两种提交方式

//mutatios.ts
import {INCREMENT} from "./mutations-types";
import store from "./index";

export default {
    
    [INCREMENT](state:any, payload:any){
        state.count = state.count + payload.count;
    },
    
}

//组件中调用
function do1() {
  		//使用普通模式
      store.commit(INCREMENT,{count:15});
  		
  		//对象风格的提交,一般使用对象提交
      store.commit({
        type: INCREMENT,
        count: 10
      })
    }

当使用对象风格的提交方式时,会将整个对象传递给payload,即type属性也在里面,不过mutation.ts中的函数处理不用更改。

action和module后期再做补充了