哈Ha! 我向您介绍Sanath Kumar 撰写的文章“精通Vuex-对英雄零” 。
Vuex官方文档将其定义为Vue.js应用程序的状态管理模式 +库。 但这是什么意思? 什么是状态管理模式?
想象一下,您正在使用具有数百种路由和组件的大型Web应用程序。 如果我们可以将一个应用程序中需要的所有数据存储在一个集中式存储中会不会更容易?

我们应用程序中的每个组件或路由都会从Vuex状态请求数据,并将更改后的数据传送回该状态。
本质上,Vuex的状态可以看作是整个应用程序唯一的真理来源。
数据作为JSON对象存储在状态内。 例如:
state: { name: "John Doe", age: "28" }
但是,我们的组件和路由如何访问存储在状态中的数据? 为此,我们需要在Vuex存储库中定义getter ,以将数据从存储库返回到我们的组件。 让我们看看一个简单的getter的样子,它从我们的存储库中获取名称:
getters: { NAME: state => { return state.name; }, }
请注意,getter名称以大写字母表示。 这只是代码风格的建议。 如果您不喜欢它,则不必遵循它。
既然我们已经为名称定义了一个getter,那么在我们的组件内部获取名称的值非常容易。 下面的代码使您可以执行此操作。
let name = this.$store.getters.NAME;
我们想出了如何从存储中获取数据。 现在,让我们看看如何在存储库中设置数据。 我们将定义二传手,对吗? 此外,Vuex设置器的命名略有不同。 我们定义一个Mutation将数据设置为Vuex状态。
mutations: { SET_NAME: (state, payload) => { state.name = payload; }, }
有效载荷还有什么? 有效负载是从构成突变的组件传输到突变的数据。 我们该怎么做? 很简单:
this.$store.commit('SET_NAME', your_name);
这段代码将更改应用程序的状态,并为存储库中的name属性设置分配给your_name的任何值。
同步同步
想象一下,我们有一个存储在远程服务器上的数据库中的名称列表。 服务器为我们提供了一个端点,该端点返回可以在我们的Vue.js中使用的名称数组。 当然,我们可以使用Axios查询端点并获取数据。
let {data} = await Axios.get('https://myapiendpoint.com/api/names');
之后,我们可以使用突变将返回的数组传递到我们的商店Vuex状态。 容易吧? 但事实并非如此。 变异是同步的,我们不能在变异内运行异步操作,例如API调用。
那我们该怎么办? 创建动作 。
动作就像突变一样,但是它们并没有直接改变状态,而是做出了突变。 听起来令人困惑? 让我们看看该动作的公告。
actions: { SET_NAME: (context, payload) { context.commit('SET_NAME', payload); }, }
我们定义了一个名为SET_NAME的动作,该动作将上下文和有效负载作为参数。 该操作将提交先前创建的变异SET_NAME,并将其传递给它的数据,即your_name 。
现在,我们的组件取代了直接调用突变的功能,而是使用新名称作为数据触发SET_NAME操作,如下所示:
this.$store.dispatch('SET_NAME', your_name);
然后,该操作会使用传递给它的数据(即your_name)来启动变异。
但是为什么呢?
您可能想知道,如果我们可以直接从组件中直接使用新值启动突变,为什么需要执行动作声明。 如上所述,突变是同步的,但没有动作。
在上面的示例中,考虑了需要更新名称值的情况,但不仅要更改名称的状态,还需要更新远程服务器上运行的数据库中的情况。 我确信这是您打算在99%的情况下在实际项目中使用Vuex的方式。 看一下以下代码片段:
mutations: { SET_NAME: (state, name) => { state.name = name; }, }, actions: { SET_NAME: async (context, name) => { let {data} = await Axios.post('http://myapiendpoint.com/api/name', {name: name}); if (data.status == 200) { context.commit('SET_NAME', name); } }, }
该代码本身是不言自明的。 我们使用Axios将名称发送到端点。 如果POST请求成功,并且在服务器上成功更改了字段名称值,我们将启动SET_ NAME突变以更新状态内的名称值。
切勿直接启动静音。 为此,请务必使用操作。
在Vue.JS中配置Vuex存储
让我们更深入地了解如何在实际应用程序中实现Vuex。
步骤1.安装Vuex
npm install --save vuex
步骤2.创建Vuex存储库
- 在应用程序的根目录中创建store目录。
- 在此目录中创建index.js文件,并使用以下代码创建新的存储库。
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); export const store = new Vuex.Store({ state: {}, getters: {}, mutations: {}, actions: {}, });
步骤3.将Vuex存储添加到Vue.JS应用程序
1.将存储库导入main.js文件:
import {store} from './store';
2.将存储添加到Vue实例,如下所示:
new Vue({ el: '#app', store, router, render: h => h(App), });
现在,我们可以将状态变量,获取器,变异和操作添加到我们的Vuex存储库中。
例子
看一下简单的待办事项列表应用程序的Vuex存储库。 “不仅仅是另一个待办事项!!!” ?? 不用担心 在本文的最后,您将学习如何使用Vuex的全部功能。
import Vue from 'vue'; import Vuex from 'vuex'; import Axios from 'axios'; Vue.use(Vuex); export const store = new Vuex.Store({ state: { todos: null, }, getters: { TODOS: state => { return state.todos; }, }, mutations: { SET_TODO: (state, payload) => { state.todos = payload; }, ADD_TODO: (state, payload) => { state.todos.push(payload); }, }, actions: { GET_TODO: async (context, payload) => { let {data} = await Axios.get('http://yourwebsite.com/api/todo'); context.commit('SET_TODO', data); }, SAVE_TODO: async (context, payload) => { let {data} = await Axios.post('http://yourwebsite.com/api/todo'); context.commit('ADD_TODO', payload); }, }, });
将新项目添加到待办事项列表
在组件内部,通过向其传递一个新的待办事项来启动SAVE_TODO操作,如下面的代码片段所示。
let item = 'Get groceries'; this.$store.dispatch('SAVE_TODO', item);
SAVE_TODO操作向端点发出POST请求,然后启动ADD_TODO突变 ,该突变将待办事项添加到待办事项状态变量。
待办事项
在组件的mount()块内,启动第二个GET_TODO操作,该操作从端点接收所有待办事项并将其存储在todos状态变量中,从而启动SET_TODO突变:
mounted() { this.$store.dispatch('GET_TODO'); }
访问组件内部的待办事项
要访问组件内部的todos元素,请创建一个计算属性:
computed: { todoList() { return this.$store.getters.TODOS; }, }
在组件内部,您可以访问计算属性:
<div class="todo-item" v-for="item in todoList"></div>
使用mapGetters方法
使用Vuex提供的mapGetters方法,还有一种更简单的方法来访问组件中的待办事项。
import {mapGetters} from 'vuex'; computed : { ...mapGetters(['TODOS']), // }
您可能已经猜到了应该更改模板内的代码,如下面的代码片段所示。
<div class="todo-item" v-for="item in TODOS"></div>
请注意,我们是如何在计算属性中使用ES6分布运算符的。
VUEX存储不只是您应用程序当前状态的来源。 这也是应该更改此状态的唯一要点。
这需要一些解释。 我们已经学习了如何在存储库中创建用于接收和安装待办事项的操作 。 如果我们需要更新元素并标记该怎么办? 为此,我们在哪里运行代码?
在互联网上,您可以找到有关此问题的不同意见。 该文档也缺乏明确的指导。
我建议将所有API调用存储在Vuex存储库中的操作内部。 因此,每个状态更改仅发生在存储库内部,从而简化了调试并简化了对代码的理解,并使编辑代码更加容易。
代码组织
一旦开始使用大型应用程序,将所有状态变量,获取器,动作和变异保存在一个文件中将很快使它变得麻烦。 让我们看看如何将多个文件存储为模块。
在存储库中创建一个新目录,并将其命名为modules 。 将todos.js文件添加到包含以下代码的已创建目录中:
const state = {}; const getters = {}; const mutations = {}; const actions = {}; export default { state, getters, mutations, actions, };
现在,我们可以将状态变量,获取器,变异和动作从index.js文件移动到todos.js文件。 记住要导入Axios 。 我们需要做的就是让Vuex知道我们已经创建了存储模块以及在哪里可以找到它。 更新后的index.js文件应如下所示:
import Vue from 'vue'; import Vuex from 'vuex'; import Axios from 'axios'; import todos from './modules/todos'; Vue.use(Vuex); export const store = new Vuex.Store({ state: {}, getters: {}, mutations: {}, actions: {}, modules: { todos, }, });
todos.js文件将如下所示:
import Axios from 'axios'; state = { todos: null, }; getters = { TODOS: state => { return state.todos; }, }; mutations = { SET_TODO: (state, payload) => { state.todos = payload; }, ADD_TODO: (state, payload) => { state.todos.push(payload); }, }; actions = { GET_TODO: async (context, payload) => { let {data} = await Axios.get('http://yourwebsite.com/api/todo'); context.commit('SET_TODO', data); }, SAVE_TODO: async (context, payload) => { let {data} = await Axios.post('http://yourwebsite.com/api/todo'); context.commit('ADD_TODO', payload); }, }; export default { state, getters, mutations, actions, };
总结
- 应用程序状态存储为一个大型JSON对象。
- 获取器用于访问存储在存储中的值。
- 突变会改变您的状况。 应该记住,突变是同步的。
- 所有异步操作必须在action中执行 。 动作改变状态,引发突变。
- 将仅通过行动启动突变作为规则。
- 模块可用于将您的存储组织成几个小文件。
Vuex使使用Vue变得更加轻松和有趣。 如果您是初学者,可能会遇到一些情况,您很难决定是否在应用程序的某些区域中使用Vuex。 跟随你的直觉。 您将很快达到高速。