Vue 全局状态管理:Vuex 从入门到精通

前言

在开发 Vue 应用时,管理组件之间的状态共享变得越来越重要。特别是当应用变得复杂,组件之间的通信越来越多时,如何有效地管理状态成为了一个重要问题。Vuex 是 Vue 提供的一种集中式状态管理模式,能够帮助开发者更好地管理应用状态,提高代码的可维护性和可扩展性。
本文将通过通俗易懂的方式介绍 Vuex 的基本用法以及一些进阶技巧,帮助你更好地掌握 Vuex。

Vuex 是什么?

Vuex 是一个专为 Vue.js 应用设计的状态管理模式。它借鉴了 Flux、Redux 等状态管理库的思想,通过一个全局的 store 来管理应用的所有状态,并且保持状态的唯一性和可预测性。

简单来说,Vuex 可以理解为一个专门用来管理应用状态的超大仓库,我们可以把应用中所有组件需要共享的状态集中放在这个仓库中。通过 Vuex,我们可以轻松地从仓库中获取状态,更新状态,并且这些状态的变化能被自动地同步到使用它们的组件中。

Vuex 的基本概念

在开始使用 Vuex 之前,我们需要了解以下几个基本概念:

  1. State:状态,存储应用的全局状态。
  2. Getter:计算属性,类似于组件中的计算属性,用于从 state 中派生一些状态。
  3. Mutation:突变,唯一可以修改 state 的方法,通过提交 mutation 来修改状态。
  4. Action:动作,和 mutation 类似,但它是用于处理异步操作的,可以包含任意异步逻辑。
  5. Module:模块,Vuex 支持将状态和变更逻辑按模块进行划分,方便管理。

Vuex 的基本使用

1. 安装 Vuex

在 Vue 项目中使用 Vuex 非常简单,首先需要进行安装:

npm install vuex --save

安装完成后,在项目中创建一个 store 文件夹,并创建一个 index.js 文件:

// src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++;
    }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => {
        commit('increment');
      }, 1000);
    }
  },
  getters: {
    doubleCount: state => state.count * 2
  }
});

export default store;

2. 在 Vue 实例中使用 Vuex

接下来,我们需要在 Vue 实例中引入并使用这个 store:

// src/main.js
import Vue from 'vue';
import App from './App.vue';
import store from './store';

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

3. 在组件中使用 Vuex

在组件中,我们可以通过 this.$store 来访问 Vuex 的状态和方法。例如:

<template>
  <div>
    <p>{{ count }}</p>
    <p>{{ doubleCount }}</p>
    <button @click="increment">Increment</button>
    <button @click="incrementAsync">Increment Async</button>
  </div>
</template>

<script>
export default {
  computed: {
    count() {
      return this.$store.state.count;
    },
    doubleCount() {
      return this.$store.getters.doubleCount;
    }
  },
  methods: {
    increment() {
      this.$store.commit('increment');
    },
    incrementAsync() {
      this.$store.dispatch('incrementAsync');
    }
  }
};
</script>

进阶技巧

1. 模块化

当应用变得复杂时,将所有的状态和变更逻辑放在一个 store 中会显得很混乱。Vuex 支持将 store 拆分成模块,每个模块都拥有自己的 state、mutation、action 和 getter。

// src/store/modules/counter.js
const state = {
  count: 0
};

const mutations = {
  increment(state) {
    state.count++;
  }
};

const actions = {
  incrementAsync({ commit }) {
    setTimeout(() => {
      commit('increment');
    }, 1000);
  }
};

const getters = {
  doubleCount: state => state.count * 2
};

export default {
  state,
  mutations,
  actions,
  getters
};

// src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import counter from './modules/counter';

Vue.use(Vuex);

const store = new Vuex.Store({
  modules: {
    counter
  }
});

export default store;

2. 使用辅助函数

Vuex 提供了一些辅助函数,帮助我们更方便地在组件中使用 state、getter、mutation 和 action。例如 mapState、mapGetters、mapMutations 和 mapActions。

<template>
  <div>
    <p>{{ count }}</p>
    <p>{{ doubleCount }}</p>
    <button @click="increment">Increment</button>
    <button @click="incrementAsync">Increment Async</button>
  </div>
</template>

<script>
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';

export default {
  computed: {
    ...mapState(['count']),
    ...mapGetters(['doubleCount'])
  },
  methods: {
    ...mapMutations(['increment']),
    ...mapActions(['incrementAsync'])
  }
};
</script>

3. 插件与持久化

1. 使用 Vuex 插件

Vuex 支持使用插件来扩展其功能。插件可以用于日志记录、状态持久化、时间旅行等。插件是一些函数,它们会接收 store 作为参数。

例如:日志插件
我们可以创建一个简单的日志插件,记录每次 mutation 的调用情况:

// src/store/plugins/logger.js
const logger = store => {
  store.subscribe((mutation, state) => {
    console.log('Mutation:', mutation.type);
    console.log('Payload:', mutation.payload);
  });
};

export default logger;

然后在创建 store 时,使用这个插件:

// src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import counter from './modules/counter';
import logger from './plugins/logger';

Vue.use(Vuex);

const store = new Vuex.Store({
  modules: {
    counter
  },
  plugins: [logger]
});

export default store;
2. 状态持久化

在开发某些应用时,我们希望在页面刷新时保持 Vuex 的状态不变。我们可以使用 Vuex 插件 vuex-persistedstate 来实现状态持久化。

安装 vuex-persistedstate:

npm install vuex-persistedstate --save

使用 vuex-persistedstate 插件:

// src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import counter from './modules/counter';
import createPersistedState from 'vuex-persistedstate';

Vue.use(Vuex);

const store = new Vuex.Store({
  modules: {
    counter
  },
  plugins: [createPersistedState()]
});

export default store;

通过这样简单的配置,Vuex 的状态就能够在页面刷新时持久化保存了。

4. 动态模块注册

在某些应用中,我们可能需要根据条件动态地注册 Vuex 模块。Vuex 提供了 registerModule 和 unregisterModule 方法来实现动态模块注册和注销。

动态注册模块
假设我们有一个用户模块,需要在用户登录后动态注册:

// src/store/modules/user.js
const state = {
  name: '',
  email: ''
};

const mutations = {
  setUser(state, user) {
    state.name = user.name;
    state.email = user.email;
  }
};

const actions = {
  login({ commit }, user) {
    // 模拟登录请求
    return new Promise(resolve => {
      setTimeout(() => {
        commit('setUser', user);
        resolve();
      }, 1000);
    });
  }
};

export default {
  state,
  mutations,
  actions
};

在组件中,我们可以动态注册和使用该模块:

<template>
  <div>
    <button @click="login">Login</button>
  </div>
</template>

<script>
import { mapActions } from 'vuex';

export default {
  methods: {
    ...mapActions(['login']),
    login() {
      const user = {
        name: 'John Doe',
        email: 'john@example.com'
      };

      this.$store.registerModule('user', require('@/store/modules/user').default);
      this.login(user).then(() => {
        console.log('User logged in');
      });
    }
  }
};
</script>

实践案例

构建一个简单的 Todo 应用

为了更好地理解和应用 Vuex,我们将通过构建一个简单的 Todo 应用来演示如何使用 Vuex 进行状态管理。

1. 项目结构
首先,让我们创建一个 Vue 项目,并安装 Vuex:

vue create vuex-todo-app
cd vuex-todo-app
npm install vuex --save

项目结构如下:

vuex-todo-app/
│
├── src/
│   ├── components/
│   │   └── TodoList.vue
│   ├── store/
│   │   └── index.js
│   ├── App.vue
│   └── main.js

2. 配置 Vuex Store
在 src/store/index.js 中配置我们的 Vuex store:

// src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const state = {
  todos: []
};

const mutations = {
  ADD_TODO(state, todo) {
    state.todos.push(todo);
  },
  REMOVE_TODO(state, index) {
    state.todos.splice(index, 1);
  },
  TOGGLE_TODO(state, index) {
    state.todos[index].completed = !state.todos[index].completed;
  }
};

const actions = {
  addTodo({ commit }, todo) {
    commit('ADD_TODO', todo);
  },
  removeTodo({ commit }, index) {
    commit('REMOVE_TODO', index);
  },
  toggleTodo({ commit }, index) {
    commit('TOGGLE_TODO', index);
  }
};

const getters = {
  completedTodos: state => state.todos.filter(todo => todo.completed),
  pendingTodos: state => state.todos.filter(todo => !todo.completed)
};

const store = new Vuex.Store({
  state,
  mutations,
  actions,
  getters
});

export default store;

3. 主文件配置
在 src/main.js 中引入和配置 store:

// src/main.js
import Vue from 'vue';
import App from './App.vue';
import store from './store';

Vue.config.productionTip = false;

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

4. 创建 TodoList 组件
在 src/components/TodoList.vue 中创建我们的 TodoList 组件:

<template>
  <div>
    <h1>Todo List</h1>
    <input v-model="newTodo" @keyup.enter="addTodo" placeholder="Add a new todo" />
    <ul>
      <li v-for="(todo, index) in todos" :key="index">
        <input type="checkbox" v-model="todo.completed" @change="toggleTodo(index)" />
        <span :class="{ completed: todo.completed }">{{ todo.text }}</span>
        <button @click="removeTodo(index)">Remove</button>
      </li>
    </ul>
    <h2>Completed Todos</h2>
    <ul>
      <li v-for="(todo, index) in completedTodos" :key="index">{{ todo.text }}</li>
    </ul>
    <h2>Pending Todos</h2>
    <ul>
      <li v-for="(todo, index) in pendingTodos" :key="index">{{ todo.text }}</li>
    </ul>
  </div>
</template>

<script>
import { mapState, mapGetters, mapActions } from 'vuex';

export default {
  data() {
    return {
      newTodo: ''
    };
  },
  computed: {
    ...mapState(['todos']),
    ...mapGetters(['completedTodos', 'pendingTodos'])
  },
  methods: {
    ...mapActions(['addTodo', 'removeTodo', 'toggleTodo']),
    addTodo() {
      if (this.newTodo.trim() !== '') {
        this.addTodo({
          text: this.newTodo,
          completed: false
        });
        this.newTodo = '';
      }
    }
  }
};
</script>

<style scoped>
.completed {
  text-decoration: line-through;
}
</style>

5. 使用 TodoList 组件
在 src/App.vue 中使用我们创建的 TodoList 组件:

<template>
  <div id="app">
    <TodoList />
  </div>
</template>

<script>
import TodoList from './components/TodoList.vue';

export default {
  name: 'App',
  components: {
    TodoList
  }
};
</script>

<style>
@import './assets/styles.css';
</style>

6. 运行应用
至此,我们的 Todo 应用已经完成。运行应用:

npm run serve

打开浏览器,访问 http://localhost:8080,你将看到一个简单的 Todo 应用,你可以添加、删除、标记完成和查看已完成或未完成的 Todo 项目。

总结

通过本文的介绍,我们了解了 Vuex 的基本概念和使用方法,并且学习了一些进阶技巧。掌握 Vuex 可以帮助我们更好地管理 Vue 应用中的状态,提高代码的可维护性和可扩展性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/908579.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙系统的优势 开发 环境搭建 开发小示例

HarmonyOS是面向多智能终端、全场景的分布式操作系统,为消费者提供跨终端的无缝体验.华为开发者联盟从HarmonyOS应用设计、开发、测试、推广变现等环节全方位助力开发者。 开发者可以通过以下步骤学习鸿蒙系统的开发&#xff1a; 基础理论学习&#xff1a; 了解鸿蒙系统概述&a…

「C/C++」C/C++的区别

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

Windows部署rabbitmq

本次安装环境&#xff1a; 系统&#xff1a;Windows 11 软件建议版本&#xff1a; erlang OPT 26.0.2rabbitmq 3.12.4 一、下载 1.1 下载erlang 官网下载地址&#xff1a; 1.2 下载rabbitmq 官网下载地址&#xff1a; 建议使用解压版&#xff0c;安装版可能会在安装软件…

el-table 滚动条重置 手动控制滚动条

最近在使用 el-table 的时候&#xff0c;出现一个问题&#xff1a; 表头过长的时候&#xff0c;会有左右滑动的操作&#xff0c;当我们把表格拉到最右侧&#xff0c;这个时候重新请求数据的话&#xff0c;表格位置还是在最右侧&#xff0c;不会恢复原位。 那我们想恢复原位&a…

推荐FileLink数据跨网摆渡系统 — 安全、高效的数据传输解决方案

在数字化转型的浪潮中&#xff0c;企业对于数据传输的需求日益增加&#xff0c;特别是在不同网络环境之间的文件共享和传输。为了满足这一需求&#xff0c;FileLink数据跨网摆渡系统应运而生&#xff0c;为企业提供了一种安全、高效的数据传输解决方案。 安全第一&#xff0c;保…

STl学习-迭代器

1.迭代器种类 这五种迭代器的声明如下&#xff1a; truct output_iterator_tag {};//输出迭代器 truct input_iterator_tag{ };//输入迭代器 truct forward iterator tag : public input iterator tag {};//向前迭代器 truct bidirectional iterator tag :public forward iter…

自适应对话式团队构建,提升语言模型代理的复杂任务解决能力

人工智能咨询培训老师叶梓 转载标明出处 如何有效利用多个大模型&#xff08;LLM&#xff09;代理解决复杂任务一直是一个研究热点。由美国南加州大学、宾夕法尼亚州立大学、华盛顿大学、早稻田大学和谷歌DeepMind的研究人员联合提出了一种新的解决方案——自适应团队构建&…

临街矩阵乘以自己转置的含义

总结: 临街矩阵* 邻接矩阵转置的(i,j) 位置表示有多少种线路从元素A跳转一条边最终落到元素j的路线. 这个也叫1_degree.

JavaEE-多线程初阶(3)

目录 1.线程的状态 1.1 NEW、RUNNABLE、TERMINATED 1.2 TIMED_WAITING 1.3 WAITING 1.4 BLOCKED 2.多线程带来的风险-线程安全&#xff08;重点&#xff09; 2.1 观察线程不安全的现象 2.2 分析产生该现象的原因 2.3 产生线程安全问题的原因 2.3.1 抢占式执行&#x…

江协科技STM32学习- P35 硬件I2C读写MPU6050

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

学习虚幻C++开发日志——定时器

官方文档&#xff1a;虚幻引擎中的Gameplay定时器 | 虚幻引擎 5.5 文档 | Epic Developer Community | Epic Developer Community 定时器 安排在经过一定延迟或一段时间结束后要执行的操作。例如&#xff0c;您可能希望玩家在获取某个能力提升道具后变得无懈可击&#xff0c;…

【简道云 -注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

【表格解决问题】EXCEL行数过多,WPS如何按逐行分别打印多个纸张中

1 问题描述 如图&#xff1a;我的表格行数太多了。打印在一张纸上有点不太好看 2 解决方式 Step01&#xff1a;先选中你需要打印的部分&#xff0c;找到【页面】->【打印区域】->【设置打印区域】 Step02&#xff1a;先选中一行&#xff0c;找到【插入分页符】 Step0…

提高交换网络可靠性之链路聚合

转载请注明出处 该实验为链路聚合的配置实验。 1.改名&#xff0c;分别将交换机1和交换机2改名为S1&#xff0c;S2&#xff0c;然后查看S1&#xff0c;S2的STP信息。以交换机1为例&#x1f447;。 2.交换机S1&#xff0c;S2上创建聚合端口&#xff0c;将端口加入聚合端口。以S…

SpringMVC笔记 一万字

此笔记来自于B站尚硅谷 文章目录 一、SpringMVC 简介1、什么是MVC2、什么是SpringMVC3、SpringMVC的特点 二、HelloWorld1、开发环境2、创建maven工程a>添加web模块b>打包方式&#xff1a;warc>引入依赖 3、配置web.xmla>默认配置方式b>扩展配置方式 4、创建请求…

【Hive sql面试题】找出连续活跃3天及以上的用户

表数据如下&#xff1a; 要求&#xff1a;求出连续活跃三天及以上的用户 建表语句和插入数据如下&#xff1a; create table t_useractive(uid string,dt string );insert into t_useractive values(A,2023-10-01 10:10:20),(A,2023-10-02 10:10:20),(A,2023-10-03 10:16…

livp是什么格式文件?这几款软件可以轻松处理!

今天&#xff0c;我们要探讨的是一种可能相对陌生但又颇具特色的文件格式——LIVP。它通常与某些特定的软件或设备相关联&#xff0c;比如某些品牌的相机或视频编辑软件。LIVP文件往往包含了丰富的图像或视频信息&#xff0c;以及与之相关的元数据&#xff08;如拍摄时间、地点…

贪心算法---java---黑马

贪心算法 1)Greedy algorithm 称之为贪心算法或者贪婪算法&#xff0c;核心思想是 将寻找最优解的问题分为若干个步骤每一步骤都采用贪心原则&#xff0c;选取当前最优解因为未考虑所有可能&#xff0c;局部最优的堆叠不一定得到最终解最优 贪心算法例子 Dijkstra while …

基于vue框架的的留守儿童帮扶管理系统c2691(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;留守儿童,帮扶活动,申请记录,帮扶机构,帮扶进度,帮扶人,申请加入记录,参与帮扶记录,地区信息 开题报告内容 基于Vue框架的留守儿童帮扶管理系统开题报告 一、研究背景与意义 在现代化进程中&#xff0c;随着城乡经济差异的不断扩大&a…

MySQL数据库迁移到DM8数据库

1. 达梦新建zsaqks库 2. 打开DM数据迁移工具 3. 新建工程 4. 迁移 - 右击 - 新建迁移 下一步 5. 选择迁移方式 6. MySQL数据源 请输入MySQL数据库信息 7. DM数据库目的 请输入达梦数据库信息 8. 迁移选项 保持对象名大小写(勾选) 9. 指定模式 指定是从数据源复制对象。 10.…