Vuex 状态管理

Vuex是一个专为Vue.js应用程序开发的状态管理模式,用于集中管理共享状态。它包括state(存储状态),getters(计算属性),mutations(同步状态变更),actions(异步操作)和modules(模块化)。Vuex强调了单向数据流和响应式状态,通过commit处理同步更新,dispatch处理异步操作,以及通过namespaced实现模块的封装和复用。

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

Vuex 状态管理

概述

Vuex 是一个专门为 Vue 开发的状态管理器。Vuex 采用集中式存储管理应用的多个组件之间的共享状态数据,并以相应的规则保证状态以一种可预测的方式发生变化。

通过使用 Vuex,可以轻松地管理 Vue 应用程序的状态,并确保所有组件都可以方便地访问和修改该状态。

Vuex 官方文档

安装框架

npm install vuex@next --save

核心概念

在这里插入图片描述

Vuex 包含7个核心概念:

  • store:管理对象,仅有一个。
  • state:存储状态数据。
  • getters:基于state的计算属性。
  • mutations:用于修改状态的方法,只能进行同步操作。
  • actions:可以同步或异步间接更新状态的方法。
  • modules:将store拆分为模块,每个模块都有自己的state、getters、mutations和actions。
  • plugins:配置插件。

在这里插入图片描述

用法

基本用法

配置 store,在 src/store 目录中新建 index.js 文件:

import {createStore} from 'vuex';

const store = createStore({
    // 状态
    state: {
        count: 0
    },
    // 计算属性
    getters: {
        addOrEven(state) {
            return state.count % 2 === 1 ? "奇数" : "偶数";
        }
    },
    // 更新状态方法
    mutations: {
        increase(state, num) {
            state.count += num;
        },
        decrease(state, num) {
            state.count -= num;
        }
    },
    // 异步或同步更新状态方法
    actions: {
        increaseAsync({commit}, num) {
            setTimeout(() => {
                commit('increase', num);
            }, 1000);
        },
        decreaseAsync(context, num) {
            setTimeout(() => {
                context.commit('decrease', num);
            }, 1000);
        },
    },
});

export default store;

配置 main.js 文件:

import {createApp} from "vue";
import "./style.css";
import App from "./App.vue";
import store from "@/store/index.js";

const app = createApp(App);
app.use(store);
app.mount("#app");

创建2个组件:

CountShow.vue:

<script setup>
import {useStore} from "vuex";

const store = useStore();
console.log("store:", store);
</script>

<template>
  <div>
    <h2>CountShow</h2>
    <p>count: {{ store.state.count }}</p>
    <p>奇数或偶数:{{ store.getters.addOrEven }}</p>
  </div>
</template>

<style scoped>
div {
  margin: 10px;
  border: 1px solid blue;
}
</style>

CountUpdate.vue:

<script setup>
import {useStore} from "vuex";

const store = useStore();
const increase = () => {
  store.commit("increase", 1);
};
const decrease = () => {
  store.commit("decrease", 1);
};
const increaseAsync = () => {
  store.dispatch("increaseAsync", 2);
};
const decreaseAsync = () => {
  store.dispatch("decreaseAsync", 2);
};
</script>

<template>
  <div>
    <h2>CountUpdate</h2>
    <button @click="increase">count++</button>
    <button @click="decrease">count--</button>
    <br>
    <button @click="increaseAsync">count+2(异步执行)</button>
    <button @click="decreaseAsync">count-2(异步执行)</button>
  </div>
</template>

<style scoped>
div {
  margin: 10px;
  border: 1px solid red;
}

button {
  margin: 5px;
}
</style>

使用这2个组件:

<script setup>
import CountShow from "@/components/CountShow.vue";
import CountUpdate from "@/components/CountUpdate.vue";
</script>

<template>
  <CountShow/>
  <CountUpdate/>
</template>

多模块开发

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块。

定义子模块,在 store 目录下新建 user/index.js 文件:

const user = {
    state: {
        name: "小明",
        age: 18
    },
    getters: {
        ageOddOrEven(state) {
            return state.age % 2 === 1 ? "奇数" : "偶数";
        }
    },
    mutations: {
        increaseAge(state, num) {
            state.age += num;
        },
        changeName(state, name) {
            state.name += name;
        }
    },
    actions: {
        increaseAgeAsync(context, num) {
            setTimeout(() => {
                context.commit('increaseAge', num);
            }, 1000);
        },
        changeNameAsync({commit}, name) {
            setTimeout(() => {
                commit('changeName', name);
            }, 1000);
        }
    }
};

export default user;

在 store 中配置多模块:

import {createStore} from 'vuex';
import user from "@/store/user/index.js";

const store = createStore({
    modules: {
        user
    }
});

export default store;

使用:

<script setup>
import store from "./store/index.js";

const changeAge = () => {
  store.commit("increaseAge", 1);
};
const changeName = () => {
  store.commit("changeName", "a");
};
const changeAgeAsync = () => {
  store.dispatch("increaseAgeAsync", 2);
};
const changeNameAsync = () => {
  store.dispatch("changeNameAsync", "b");
};
</script>

<template>
  <p>name: {{ store.state.user.name }}</p>
  <p>age: {{ store.state.user.age }}</p>
  <p>age是奇数还是偶数: {{ store.getters.ageOddOrEven }}</p>
  <button @click="changeAge">修改age</button>
  <button @click="changeName">修改name</button>
  <button @click="changeAgeAsync">修改age(异步执行)</button>
  <button @click="changeNameAsync">修改name(异步执行)</button>
</template>

命名空间

在多个Vuex模块中有相同名称的mutation方法或action方法,那么一旦在组件中调用store对象的commit方法或dispatch方法,所有模块中匹配对应名称的mutation方法和action方法就都会执行

Vuex 支持命名空间,方便指定使用某个模块。

定义子模块,在 store 目录下新建 student/index.js 文件:

const student = {
    namespaced: true, // 开启命名空间
    state: {
        age: 18
    },
    getters: {
        oddOrEven(state) {
            return state.age % 2 === 1 ? "奇数" : "偶数";
        }
    },
    mutations: {
        increaseAge(state, num) {
            state.age += num;
        }
    },
    actions: {
        increaseAgeAsync(context, num) {
            setTimeout(() => {
                context.commit('increaseAge', num);
            }, 1000);
        }
    }
};

export default student;

配置多模块:

import {createStore} from 'vuex';

const store = createStore({
    modules: {
        student
    }
});

export default store;

使用:

<script setup>
import store from "./store/index.js";

const changeStuAge = () => {
  store.commit("student/increaseAge", 1);
};
const changeStuAgeAsync = () => {
  store.dispatch("student/increaseAgeAsync", 2);
};
</script>

<template>
  <p>student age:{{ store.state.student.age }}</p>
  <p>student name:{{ store.getters["student/oddOrEven"] }}</p>
  <button @click="changeStuAge">修改age</button>
  <button @click="changeStuAgeAsync">修改age(异步执行)</button>
</template>

持久化处理

可以借助第三方插件 vuex-persistedstate 实现持久化,存储在 LocalStorage 中。

下载工具包:

npm install vuex-persistestate

在 store 中配置持久化插件:

import {createStore} from 'vuex';
import user from "@/store/user/index.js";
import student from "@/store/student/index.js";
import createPersistedState from "vuex-persistedstate";

const store = createStore({
    modules: {
        user,
        student,
    },
    // 配置插件
    plugins: [
        // createPersistedState() // 持久化缓存所有状态
        createPersistedState({ 
            paths:["student"], // 只缓存student模块
        })
    ]
});

export default store;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值