vue3+ts vuex的使用

1、state

state写法有变化,新版state的写法和vue2的data写法神似,是一个函数返回一个对象,而不是一个普通的对象了。由于是用ts写的,所以创建的state一定要有类型。

import { createStore } from "vuex";

//一定要有类型
interface States {
  count: number;
}

// 创建一个新的 store 实例
const store = createStore<States>({
  state() {
    return {
      count: 0,
    };
  },
});

export default store;

1.1 在组件中使用

在组件里面要使用vuex里面的state数据,首页组件导入store文件,然后store.state.xxx(数据名)就可以获取数据了。

import store from "@/store";
onMounted(() => {
  console.log(store.state.count);
});

2、mutations

mutations同样是用来改变state里面的数据,而且是同步的操作,必须使用mutations来更改state里面的数据。mutations里面的函数第一个参数接收一个state,这样就能更改state里的数据了。第二个参数也叫载荷,也就是使用的时候可以传入额外的参数,如果有多个,可以传入一个对象。

import { createStore } from "vuex";

//一定要有类型
interface States {
  count: number;
}

// 创建一个新的 store 实例
const store = createStore<States>({
  state() {
    return {
      count: 0,
    };
  },
 mutations:{
   increment(state:any,value:number):void{
      state.count+=value;
   }
 }

});

export default store;

2.1 在组件中使用

在组件中使用mutations来更改state里面的数据,一定要使用commit来提交一个申请,使用格式:store.commit("定义好的函数名",传入的参数)。注意mutations只能执行同步的操作,异步的操作执行不了!!!

import store from "@/store";
onMounted(() => {
 //括号里面的名称对应的是想触发的mutations里面函数的名称,后面是参数,这样就会触发store里面的mutations的increment函数。
  store.commit("increment",1)
});

3、actions

和以前一样,actions负责异步的更改state数据,但是它不能直接更改,而是提交一个mutations,触发mutations来更改state的数据。Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 来获取 state。第二个参数同样是一个载荷,也就是额外的参数。

import { createStore } from "vuex";

//一定要有类型
interface States {
  count: number;
}

// 创建一个新的 store 实例
const store = createStore<States>({
  state() {
    return {
      count: 0,
    };
  },
 mutations:{
   increment(state:any,value:number):void{
      state.count+=value;
   }
 }
 actions:{
  //这个名字可以随便起,和上面一样也没关系。函数里面进行了commit mutations,提交了mutations里面的increment,触发了increment这个函数,把 
    额外的参数传进去,mutations里面的increment负责更改state的count。
   incrementAction(context:any,value:number){
      context.commit("increment",value)
   }
 }
//官网给出一种解构的写法,因为context和store一样有相同的方法和属性,所以也有commit,把commit解构出来 {commit} 就变成了官网的那种写法

});

export default store;

3.1 在组件中使用

注意因为actions里面的必须是异步操作,所以在使用的时候也必须是异步的才能使用,比如点击按钮,让state的count加1,用dispatch触发actions

<template>
  <div class="home">
    <el-button type="primary" round @click="onSubmit">Primary</el-button>
  </div>
</template>
import store from "@/store";
const onSubmit = () => {
  store.dispatch("incrementAction", 1);
};

4、getters

有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:如果有多个组件需要用到此属性,我们要么复制这个函数,或者 抽取到一个共享函数然后在多处导入它——无论哪种方式都不是很理想。Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。

import { createStore } from "vuex";

//一定要有类型
interface States {
  count: number;
  todo:any[];
}

// 创建一个新的 store 实例
const store = createStore<States>({
  state() {
    return {
      count: 0,
      todo:[{age:2},{age:3},{age:4}]
    };
  },
  getters:{
    getArray:(state:any)=>{
      return state.todo.filter((item:any)=>item.age>=3);
    }
  }

});

export default store;

4.1 组件中的使用

直接store.state.getArray就可以得到过滤后的数据了

5、modules

如果store中的内容过多我们可以按照功能模块分成多个modules,每一个都有和大store有相同的state、mutations等数据。如果不开启命名空间,小模块和大的store有相同的函数名,那么在别的组件调用的时候,相同函数名的都会调用,调用的方法和以前一样。如果功能很复杂数据很多的话建议开启命名空间。

5.1、namespaced

一定要注意,是namespaced,最后面是d,之前一直丢了d这个字母,一直报错type找不到,找了好久原因!!!
实现有个user的模块,以下的代码结构:


store下面index文件是大的模块,modules文件夹下面是小的模块,state文件夹放的是模块state的类型。

store下面的index.ts:

import { createStore } from "vuex";
import OtherType from "./states/index";
import user from "./modules/user";

interface CommonState {
  name: string;
  age: number;
  count: number;
}
type states = CommonState & OtherType;

// 创建一个新的 store 实例
const store = createStore<states>({
  state() {
    return {
      count: 0,
      name: "张三",
      age: 10,
    };
  },
  mutations: {
    increment(state) {
      state.count++;
    },
  },
  actions: {
    increment({ commit }: any, value: number) {
      commit("increment", value);
    },
  },
  modules: {
    user,
  },
});

export default store;

modules下的user.ts:

import UserState from "../states/userType";

const user = {
  namespaced: true,
  state: (): UserState => ({
    name1: "李四",
    age: 10,
    todo: [{ age: 1 }, { age: 3 }, { age: 4 }],
  }),
  mutations: {
    changeName(state: any, value: string): void {
      state.name1 = value;
      console.log(state.name1);
    },
  },
  actions: {
    changeName({ commit }: any, value: string): void {
      commit("changeName", value);
    },
  },
  getters: {
    getArray: (state: any) => {
      return state.todo.filter((itme: any) => itme.age >= 3);
    },
  },
};

export default user;

state下的userType.ts:

interface TodoType {
  age: number;
}
export default interface UserState {
  name1: string;
  age: number;
  todo?: TodoType[];
  aa?: boolean;
}

index.ts:

import UserState from "./userType";

export default interface OtherType {
  user?: UserState;
}

子模块开启命名空间之后,使用子模块的方法,只需要在方法前面加上模块名字就行。我上面的模块名称是user,如果使用changeName这个函数,就是store.commit("user/changeName",'123') store.dispatch("user/changeName",'123')。访问子模块state中的数据,store.state.user.name1
还有很多子模块和主模块的参数,详情见官网。

6、组合式API

可以通过调用 useStore 函数,来在 setup 钩子函数中访问 store。

<script lang="ts" setup>
import { useStore } from 'vuex'
   const store = useStore()
</script>

为了访问 state 和 getter,需要创建 computed 引用以保留响应性,这与在选项式 API 中创建计算属性等效。
要使用 mutation 和 action 时,只需要在 setup 钩子函数中调用 commit 和 dispatch 函数。

7、InjectionKey

正常使用useStore的时候,取出来的数据是any的类型,如果想要取出的数据是带类型的,可以用InjectionKey,具体使用方法见官网,vuex篇章useStore 组合式函数类型声明。但是如果使用我在上面的方法直接导入store.index文件,这样的话是带类型的 import store from '../store/index'

猜你喜欢

转载自blog.csdn.net/a2367994141/article/details/130623492