Vuex基本使用

Vuex

一、简介

在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。

原理图:
请添加图片描述

安装:

//	vue2	==>	vuex3.x				vue3	==>	vue4.x
yarn add vuex@3

二、Vuex的环境搭建

1.创建文件:src/store/index.js

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

// actions - 响应组件中的动作       mvc中的service层
const actions = {}

// mutations - 用于操作数据(state)      mvc中的dao层
const mutations = {}

// state   -    存储数据
const state = {}


Vue.use(Vuex);	//	需要在创建store实例前调用Vue.use(Vuex)
// 创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state
})

2.main.js中创建store配置项

import store from './store'

const vm = new Vue({
    render: h => h(App),
    store
});
vm.$mount('#root')

三、基本使用

1.初始化数据、配置actions、配置mutations,操作文件store.js


const actions = {
    incre(context, value) { //  context 类似于mini版的Store
        context.commit('INCRE', value);
    }
}

const mutations = {
    INCRE(state, value) {
        state.total += value;
    }
}

const state = {
    total: 0
}

Vue.use(Vuex);
export default new Vuex.Store({
    actions,
    mutations,
    state
})

2.组件中读取vuex中的数据:$store.state.sum

<h2>当前求和为:{{ $store.state.total }}</h2>

3.组件中修改vuex中的数据:$store.dispatch('action中的方法名',数据)$store.commit('mutations中的方法名',数据)

this.$store.dispatch('incre',this.operated_n);

this.$store.commit('DECRE', this.operated_n);	//若没有网络请求或其他业务逻辑,可不写dispatch,直接编写commit
//另一种提交风格
 this.$store.commit({
 type:'DECRE',
 id:'1'
 })
 // type就是提交的类型 其它为提交的参数

4.开发者工具

请添加图片描述

三、getters配置

简述:当state中的数据需要经过加工后再使用时,可以使用getters加工。

编码使用:在store.js中追加getters配置

// 用于将state中的数据进行加工
const getters = {
    bigSum(state){
        return state.total*10;				// vue 中的data
    }
}

Vue.use(Vuex);
export default new Vuex.Store({				// vue computed
    ...
    getters
})

组件中读取数据:$store.getters.bigSum

四、四个map方法的使用

1.mapState

用于帮助我们映射state中的数据为计算属性

编码:

import { mapState } from "vuex";


coumputed:{
    /* 原生
    he() {
        return this.$store.state.total;
    }
    */
    
    // 对象写法
    ...mapState({
        he:'total',
        n: (state) => state.n,
    })
    
    
    
    /* 原生
    total() {
        return this.$store.state.total;
    }
    */
    
    // 数组写法
    ...mapState(['total'])
}

2.mapGetters

用于帮助我们映射getters中的数据为计算属性

编码:

import { mapGetters } from "vuex";


coumputed:{
    /* 原生
     dashu() {
      return this.$store.getters.bigSum;
    },
    */
    
    // 对象写法
    ...mapGetters({
        dashu:'bigSum'
    })
    
    
    
    /* 原生
    bigSum() {
        return this.$store.getters.total;
    }
    */
    
    // 数组写法
    ...mapGetters(['bigSum'])
}

3.mapMutations

简述:生成与mutations对话的方法,即:包含$store.commit(xxx)的函数

编码:

/* 原生
incre() {
    this.$store.commit("INCRE", this.operated_n);
}


由 ...mapMutations生成的函数,需要在函数调用时传参
incre(value) {
    this.$store.commit("INCRE", value);
}
*/

//对象写法
...mapMutations({
    incre:'INCRE'
})
// 使用 
<button @click="incre(1)">+</button>


//数组写法
...mapMutations(['INCRE'])
// 使用 
<button @click="INCRE(1)">+</button>

4.mapActions

编码:

/* 原生
jia(){
    this.$store.dispatch('incre',this.operated_n);
}


由 ...mapActions生成的函数,需要在函数调用时传参
jia(value) {
    this.$store.dispatch("incre", value);
}
*/

//对象写法
...mapActions({
    jia:'incre'
})
// 使用 
<button @click="jia(1)">+</button>


//数组写法
...mapMutations(['incre'])
// 使用 
<button @click="incre(1)">+</button>

5.辅助函数在setup中使用

在setup中使用mapState与mapGetters有变化,返回的函数使用了this,但setup中没有this,需要绑定this后,在使用computed函数包裹,当在外部使用,如用于事件的回调时,mapMutation,mapActions所返回的函数,可直接使用,不需要封装,因为不在setup函数中使用,当需要在setup中使用时,还是需要封装,改变this的指向,建议统一封装一下。
mapState、mapGetters使用:

import { useStore } from "vuex";
import { computed } from "vue";
import { mState,mGetters } from '../hooks/VuexAssist'
export default {
setup() {
  const store = useStore();

  // 从store中获取单个数据
  const sCounter = computed(() => store.state.count);

  const storeState = mState({counter:'count', n:'name'});
  const storeGetters = mGetters(['bigCount']);
  return {
    sCounter,
    ...storeState,
    ...storeGetters
  };
},

封装处理mapState在setup中使用:

import { computed } from "vue";
import { mapState, mapGetters, useStore } from "vuex";

const transformMap = (nativemap) => {
  const store = useStore();
  // 改变返回的函数的 this 指向,使其可以被调用,然后再传回computed
  for (let key in nativemap) {
    nativemap[key] = computed(nativemap[key].bind({ $store: store }));
  }
  return nativemap;
};

const mState = (mapSateInfo) => {
  const mapResult = mapState(mapSateInfo);
  return transformMap(mapResult);
};

const mGetters = (mapGettersInfo) => {
  const mapResult = mapGetters(mapGettersInfo);
  return transformMap(mapResult);
};

export { mState, mGetters };

mapMutations使用:

setup() {
const store = useStore();

const storeMutations = mapMutations(["increment"]);
const incre = () => {
    // 将函数在setup中执行,需要改变this指向
  storeMutations.increment.bind({$store: store})();
};
return {
  ...storeMutations, // 将函数在setup外执行,不需要改变this指向
  incre
};

封装工具函数:

import { computed } from "vue";
import {
  mapState,
  mapGetters,
  useStore,
  mapActions,
  mapMutations,
  createNamespacedHelpers,
} from "vuex";

const transformFn = (isWapperComputed) => {
  return (nativemap) => {
    // 用于作用mapSate、mapGetters,改变this指向,并包裹computed
    const store = useStore();
    if (isWapperComputed) {
      // state/getters需要包裹computed
      for (let key in nativemap) {
        nativemap[key] = computed(nativemap[key].bind({ $store: store }));
      }
    } else {
      // actions/mutations不需要包裹computed
      for (let key in nativemap) {
        nativemap[key] = nativemap[key].bind({ $store: store });
      }
    }
    return nativemap;
  };
};

/**
 * 
 * @param {*} mFn 需要转换的映射方法
 * @param {*} mFnName 需要转换的方法名,用于获取模块化的映射方法
 * @param {*} transformFn 返回 用于改变map返回的函数达的this指向的 方法
 * @returns 
 */
const mapperFn = (mFn, mFnName, transformFn) => {
  // 函数柯里化
  return (...args) => {
    let mapper = null;
    if (args.length === 1) {
      // 只有一个参数时,就没有模块化获取数据,直接获取rootState的数据
      mapper = args[0];
      return transformFn(mFn(mapper));
    }
    if (args.length === 2) {
      // 获取模块名称 映射信息
      const module = args[0];
      mapper = args[1];
      if (typeof module === "string" && module.length > 0) {
        // 判断模块名称是否存在
        mFn = createNamespacedHelpers(module)[mFnName];
        const mapResult = mFn(mapper);
        return transformFn(mapResult);
      } else {
        throw new Error("first argument must be a string and not empty");
      }
    }
    throw new Error("useSate must be called with one or two arguments");
  };
};
const useState = mapperFn(mapState, "mapState", transformFn(true));
const useGetters = mapperFn(mapGetters, "mapGetters", transformFn(true));
const useMutations = mapperFn(mapMutations, "mapMutations", transformFn(false));
const useActions = mapperFn(mapActions, "mapActions", transformFn(false));

export { useState, useGetters, useMutations, useActions };

五、Vuex模块化+命名空间

简述:让多种数据分裂明确,代码更容易维护

修改store.js

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

// Count组件相关数据
const countOptions = {
    namespaced:true,        // 如果不起开,不能使用mapState等简写方式映射,只能this.$store.count.total
    actions:{...},
    mutations:{...},
    state:{...},
    getters:{...}
}

// Person组件相关数据
const personOptions = {
    namespaced:true,
    actions:{...},
    mutations:{...},
    state:{
        personList: [
            { id: "001", name: "六七", age: 19 },
            { id: "002", name: "十三", age: 23 },
            { id: "003", name: "五四", age: 18 }
        ]
    },
    getters:{...}
}


Vue.use(Vuex);
export default new Vuex.Store({
    modules:{
        person:personOptions,
        count:countOptions
    }
})

1. 读取state

//方式一:自己直接读取
this.$store.state.personAbout.list;

//方式二:借助mapState读取:
...mapState('countAbout',['sum','school','subject'])	// 前一个参数标识模块名称

2.读取getters

//方式一:
this.$store.getters['person/fitstPersonName'];		// 写原生的,除了state,都是 ['person/fitstPersonName'] 形式获取

//方式二:借助mapGetters读取:
...mapGetters('person',['fitstPersonName'])

3.调用dispatch

//方式一:自己直接dispatch
this.$store.dispatch('count/incre',person)

//方式二:借助mapActions:
...mapActions('count',['incre'])

4.调用commit

//方式一:自己直接commit
 this.$store.commit('person/ADDPERSON',personObj);

//方式二:借助mapMutations:
...mapMutations('person',['ADDPERSON']),

5.使用createNamespacedHelpers

获取某个模块的mapState、mapGetters、mapActions、mapMutations

<script>
import { createNamespacedHelpers } from "vuex";

const { mapState: home_mapState,mapMutations,mapGetters,mapActions } = createNamespacedHelpers("home");
export default {
  computed: {
    ...home_mapState(["homeCounter"]),
  },
};
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值