优秀的编程知识分享平台

网站首页 > 技术文章 正文

Vue3,Vuex,集中式状态(数据)管理,四个模块:state、getter

nanyue 2024-10-02 17:48:25 技术文章 7 ℃

Vuex,集中式状态(数据)管理

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

vuex分为state、getter、mutation、action四个模块,其作用:

1、state:定义变量。

2、getters:获取变量。

3、mutations:同步执行对变量进行的操作。

4、actions:异步执行对变量进行的操作。

vuex中的mapState,mapGetters,mapMutations,mapActions均是辅助函数:

1、mapState:state的辅助函数。

2、mapGetters::getters的辅助函数。

3、mapMutations::mutations的辅助函数。

4、mapActions::actions的辅助函数。

Vuex,案例代码

案例一:

效果

index.js

import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
// 路由
import router from './router'
// 引入vuex
// import store from './store'
import store from './views/vuex/demo01/vuex01Store';
//import store from './views/vuex/demo02/vuex02Store';
// 引入element-plus&&引入element-plus的样式
import ElementPlus from 'element-plus'
import 'element-plus/theme-chalk/index.css' 
// I18N=>zh_cn
import zhCn from 'element-plus/es/locale/lang/zh-cn'
// 统一导入element svg(全局注册)
import * as ELIcons from '@element-plus/icons-vue';

const app = createApp(App);
// 路由
app.use(router);
// vuex
app.use(store);
// element-plus
app.use(ElementPlus, { locale: zhCn, zIndex: 3000, size: 'small' });
// 循环导入图标
for (let iconName in ELIcons) {
	app.component(iconName, ELIcons[iconName])
}
app.mount('#app');

views/vuex/demo01/vuex01Store.js

//引入Vuex
import Vuex from 'vuex';

const store = new Vuex.Store({
    //state用于存储数据
    state: {
        //当前的和
        sum: 0,
        school: '社会学院',
        subject: '编程',
    },
    // 
    getters: {
        sum(state){
            return state.sum;
        },
        tenfoldSum(state) {
            return state.sum * 10
        }
    },
    //mutations用于操作数据(state)
    mutations: {
        // 方法
        increment(state, value) {
            console.log('mutations中的increment()被调用了')
            state.sum += value;
        },
        // 方法
        decrement(state, value) {
            console.log('mutations中的decrement()被调用了')
            state.sum -= value;
        },
    },
    //actions用于响应组件中的动作
    actions: {
        // 方法
        incrementOdd(context, value) {
            console.log('actions中的incrementOdd被调用了')
            if (context.state.sum % 2) {
                context.commit('increment', value)
            }
        },
        // 方法
        incrementWait(context, value) {
            console.log('actions中的incrementWait被调用了')
            setTimeout(() => {
                context.commit('increment', value)
            }, 800)
        }
    }
});

// 创建并暴露store
export default store;

views/vuex/demo01/vuex01Manage.vue

<template>
  <div id="vuex01Manage">
    <h1>{{ name }}</h1>
    <p>{{ desc }}</p>
    <Child></Child>
    <br />
  </div>
</template>

<script>
import { ref, reactive, toRefs } from "vue";
import Child from "./vuex01Child.vue";
export default {
  name: "我是父组件",
  components: { Child: Child },
  setup(props, context) {
    let data = reactive({ name: "我是父组件.vuex01Manage" });
    let desc = ref("父组件的描述");
    return {
      ...toRefs(data),
      desc,
    };
  },
};
</script>

<style lang="css">
#vuex01Manage {
  background-color: rgb(223, 171, 180);
}
</style>

views/vuex/demo01/vuex01Child.vue

<template>
  <div id="vuex01Child">
    <h2>{{ name }}</h2>
    <!-- 在模板文件中读取数据,不需要this -->
    <h3>当前求和为:{{ $store.state.sum }}</h3>
    <h3>当前求和放大10倍为:{{ $store.getters.tenfoldSum }}</h3>
    <h3>我在{{ school }},学习{{ subject }}~</h3>
    <select v-model.number="num">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
    <button @click="incrementOdd">当前求和为奇数时再加</button>
    <button @click="incrementWait">等一等再加</button>
  </div>
</template>

<script>
export default {
  name: "vuex01Child",
  data() {
    return {
      name: "我是子组件.vuex01Child",
      // 数字
      num: 1,
    };
  },
  computed: {
    sum() {
      return this.$store.state.sum;
    },
    school() {
      return this.$store.state.school;
    },
    subject() {
      return this.$store.state.subject;
    },
  },
  methods: {
    // vuex中store.commit和store.dispatch的区别及用法
    // commit:同步操作,数据提交至mutations,可用于读取信息写到缓存里。
    // dispatch:含有异步操作,数据提交至actions,可用于向后台提交数据。
    // 加
    increment() {
      console.log(this.$store);
      this.$store.commit("increment", this.num);
    },
    // 减
    decrement() {
      this.$store.commit("decrement", this.num);
    },
    // 奇数
    incrementOdd() {
      this.$store.dispatch("incrementOdd", this.num);
    },
    // 等待后增加
    incrementWait() {
      this.$store.dispatch("incrementWait", this.num);
    },
  },
  mounted() {
    console.log("vuex01Child", this);
  },
};
</script>

<style lang="css" scoped>
#vuex01Child {
  margin: 0 auto;
  width: 600px;
  background-color: rgb(211, 119, 134);
}
button {
  margin-left: 5px;
  background-color: rgb(250, 222, 222);
  border-block-color: #fff;
}
</style>

案例二:

效果

views/vuex/demo02/vuex02Store.js

//引入Vuex
import Vuex from 'vuex';

const store = new Vuex.Store({
    //state用于存储数据
    state: {
        //当前的和
        sum: 0,
        school: '社会学院2',
        subject: '编程2',
    },
    // 
    getters: {
        sum(state) {
            return state.sum;
        },
        tenfoldSum(state) {
            return state.sum * 10
        }
    },
    //mutations用于操作数据(state)
    mutations: {
        // 方法
        increment(state) {
            console.log('mutations中的increment()被调用了')
            state.sum += 1;
        },
        // 方法
        decrement(state) {
            console.log('mutations中的decrement()被调用了')
            state.sum -= 1;
        },
    },
    //actions用于响应组件中的动作
    actions: {
        // 方法
        incrementOdd(context, value) {
            console.log('actions中的incrementOdd被调用了')
            if (context.state.sum % 2) {
                context.commit('increment', value)
            }
        },
        // 方法
        incrementWait(context, value) {
            console.log('actions中的incrementWait被调用了')
            setTimeout(() => {
                context.commit('increment', value)
            }, 800)
        }
    }
});

// 创建并暴露store
export default store;

views/vuex/demo02/vuex02Manage.vue

<template>
  <div id="vuex02Manage">
    <h1>{{ name }}</h1>
    <p>{{ desc }}</p>
    <Child></Child>
    <br />
  </div>
</template>

<script>
import { ref, reactive, toRefs } from "vue";
import Child from "./vuex02Child.vue";
export default {
  name: "我是父组件",
  components: { Child: Child },
  setup(props, context) {
    let data = reactive({ name: "我是父组件.vuex02Manage" });
    let desc = ref("父组件的描述");
    return {
      ...toRefs(data),
      desc,
    };
  },
};
</script>

<style lang="css">
#vuex02Manage {
  background-color: rgb(209, 223, 171);
}
</style>

views/vuex/demo02/vuex02Child.vue

<template>
  <div id="vuex02Child">
    <h2>{{ name }}</h2>
    <!-- 在模板文件中读取数据,不需要this -->
    <h3>当前求和为:{{ sum }}</h3>
    <h3>当前求和放大10倍为:{{ tenfoldSum }}</h3>
    <h3>我在{{ school }},学习{{ subject }}~</h3>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
    <button @click="incrementOdd">当前求和为奇数时再加</button>
    <button @click="incrementWait">等一等再加</button>
    <br />
  </div>
</template>

<script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
export default {
  name: "vuex02Child",
  data() {
    return {
      name: "我是子组件.vuex02Child",
      // 数字
      num: 1,
    };
  },
  computed: {
    // 借助mapState生成计算属性,从state中读取数据(对象写法)
    // 借助mapState生成计算属性,从state中读取数据(数组写法)
    // ...mapState({ sum: "sum", school: "school", subject: "subject" }),
    ...mapState(["sum", "school", "subject"]),

    // 借助mapGetters生成计算属性,从getters中读取数据(对象写法)
    // 借助mapGetters生成计算属性,从getters中读取数据(数组写法)
    ...mapGetters({ tenfoldSum: "tenfoldSum" }),
    // ...mapGetters(['tenfoldSum']),
  },
  methods: {
    //借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
    //借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(数组写法)
    ...mapMutations({ increment: "increment", decrement: "decrement" }),
    // ...mapMutations(['increment','decrement']),

    // 借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
    // 借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(数组写法)
    //...mapActions({incrementOdd:'incrementOdd',incrementWait:'incrementWait'})
    ...mapActions(["incrementOdd", "incrementWait"]),
  },
  mounted() {
    console.log("vuex01Child", this);
  },
};
</script>

<style lang="css" scoped>
#vuex02Child {
  margin: 0 auto;
  width: 600px;
  background-color: rgb(176, 211, 119);
}
button {
  margin-left: 5px;
  background-color: rgb(223, 250, 222);
  border-block-color: #fff;
}
</style>
最近发表
标签列表