一、Vuex简介
1.1 定义
Vuex是一个专为Vue.js应用程序开发的状态管理模式与库。它用于管理Vue.js应用程序中的状态(state)和数据流,以确保状态在不同组件之间的一致性和可维护性。Vuex基于Flux和Redux的思想,提供了一种集中管理和跟踪状态变化的机制,特别适用于大型和复杂的前端应用程序。
1.2 Vuex关键概念
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以一种可预测的方式进行状态的变更。以下是 Vuex 的关键概念:
- State(状态):
- State 即应用的状态,是存储在 Vuex 中的数据。在 Vuex 的 store 中,所有的状态都被集中存储。
- State 是响应式的,当 State 的数据发生变化时,相关的组件将自动更新。
- Getter(获取器):
- Getter 类似于组件中的计算属性。它们的作用是对 Store 中的 State 进行一些处理,然后输出处理后的结果。
- Getter 可以接受其他 Getter 作为第二个参数。
- Mutation(突变):
- Mutation 是 Vuex 中更改 State 的唯一方式。Mutation 必须是同步函数,用于改变 State 中的数据。
- 每个 Mutation 都有一个字符串的事件类型(type)和一个回调函数,回调函数就是实际进行状态更改的地方。
- 在组件中提交 Mutation 的方法是
this.$store.commit('mutationType')
。
- Action(动作):
- Action 类似于 Mutation,不同之处在于 Action 提交的是 Mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。通过 Action 可以提交多个 Mutation。
- 在组件中分发 Action 的方法是
this.$store.dispatch('actionType')
。
- Module(模块):
- 在大型应用中,单一的 State 树很容易被各种功能模块儿淹没。Module 允许我们将 State 分割成模块,每个模块有自己的 State、Getter、Mutation 和 Action。
- 模块内部的 Mutation 和 Action 可以接收和操作模块内部的局部状态。
1.3 使用Vuex的优势
使用Vuex的主要优势包括:
- 集中式管理:Vuex通过单一的存储仓库来管理应用程序的状态,使状态变化可追踪和可维护。
- 数据共享:可以轻松地在不同的组件之间共享和传递状态数据,而不需要通过组件之间的繁琐的通信手段。
- 开发工具支持:Vue.js的开发工具提供了对Vuex的强大支持,可以方便地查看状态快照、时间旅行调试等。
- 可测试性:由于Vuex的状态管理是纯粹的,你可以更容易地编写单元测试来验证你的状态和逻辑。
1.4 Vuex中各个js文件的用途
在一个典型的Vuex项目中,通常会有一些不同的JavaScript文件,每个文件都有特定的用途。以下是这些文件的一般用途:
- store.js:
- 用途:这是Vuex的核心文件,包含了Vuex的Store实例的配置和创建。
- 内容:
- 导入Vue和Vuex库。
- 导入模块(如果有多个模块)。
- 创建Vuex的Store实例,配置state、mutations、actions、getters等。
- 导出Store实例,以便在Vue应用程序中使用。
- state.js(可选):
- 用途:将应用程序的状态(state)单独抽取到一个文件中,以便更好地组织和维护状态数据。
- 内容:仅包含应用程序的状态数据。
- mutations.js(可选):
- 用途:将突变(mutations)函数单独抽取到一个文件中,以便更好地组织和维护状态变更逻辑。
- 内容:包含突变函数,这些函数用于同步修改状态。
- actions.js(可选):
- 用途:将动作(actions)函数单独抽取到一个文件中,以便更好地组织和维护异步操作逻辑。
- 内容:包含动作函数,这些函数用于执行异步任务并触发突变来修改状态。
- getters.js(可选):
- 用途:将获取器(getters)函数单独抽取到一个文件中,以便更好地组织和维护状态的派生数据。
- 内容:包含获取器函数,这些函数用于从状态中获取计算属性。
- modules/ 文件夹(可选):
- 用途:当应用程序变得复杂时,可以将Vuex的Store模块化,将不同模块的状态、突变、动作和获取器分别放在不同的文件中,以便更好地组织和管理代码。
- 内容: 包含不同模块的
state.js
、mutations.js
、actions.js
和getters.js
等文件,用于组织和管理不同模块的代码。
以上文件的具体结构和文件名可以根据项目的需求和组织方式来定制,但这种组织方式有助于保持代码的可维护性和可读性,并更好地分离关注点。
1.5 Vuex各组件
1.5.1 图解
1.5.2 详解
在一个Vue.js应用程序中,通过Vuex进行状态管理时,通常涉及多个组件。以下是一些常见的Vuex组件的角色和功能:
- 根组件(Root Component):
- 角色: 通常是Vue应用的根组件,如App.vue。
- 功能: 作为整个应用的入口点,可以在根组件中通过
this.$store
来访问和传递状态。
- 容器组件(Container Components):
- 角色: 也称为Smart组件或父组件,通常包含了子组件,并负责管理状态。
- 功能: 负责获取状态、触发动作、将状态传递给子组件,并监听状态变化以更新子组件。
- 展示组件(Presentational Components):
- 角色: 也称为Dumb组件或子组件,通常只关心UI呈现和用户交互。
- 功能: 接收父组件传递的状态和方法,负责呈现数据和用户界面。
- Getter组件(Getter Components):
- 角色: 特殊的子组件,专门用于获取Vuex的Getter中的数据。
- 功能: 通过计算属性或方法获取派生数据,然后呈现在UI中。
- Mutation组件(Mutation Components):
- 角色: 特殊的子组件,专门用于触发Vuex的Mutation以修改状态。
- 功能: 通常包含按钮或表单,当用户执行某个操作时,触发Mutation来更新状态。
- Action组件(Action Components):
- 角色: 特殊的子组件,专门用于触发Vuex的Action以执行异步操作。
- 功能: 通常包含表单或交互,当用户需要执行异步操作时,触发Action来执行复杂逻辑并更新状态。
这些组件之间的交互和关系构成了一个完整的Vue.js应用程序,其中状态由Vuex进行管理。容器组件负责连接Vuex Store和展示组件,Getter组件用于获取状态,Mutation组件用于修改状态,而Action组件用于执行异步操作。根组件通常是整个应用的入口点,并将状态传递给容器组件。这种组件分层结构有助于代码的组织和维护,以及更好的可维护性和可测试性。
1.6 变量传值的演变形式
二、Vuex获取值
2.1 安装
下载Vuex,指令代码如下:
npm install vuex -S
npm i -S vuex@3.6.2
注:mockjs版本不同,所需执行的下载安装指令也相对应不同。
下载过程:
出现版本号即安装成功:
安装完成之后,开始进行代码优化。
注:本篇博客是基于上篇博客代码的基础上优化的,详情请点击:
2.2 菜单栏
在src中创建一个vuex的目录,在改目录下创建两个组件page1,page2
代码如下:
page1:
<template> <div style="padding: 60px;"> <h1>刘三金的羁绊</h1> <p>改变state中的值</p> 请输入你的初恋:<input v-model="msg" /> <button @click="fun1">获取state</button> <button @click="fun2">改变state</button> </div> </template> <script> export default { data() { return { msg: '默认值' }; }, methods: { fun1() { // 获取 Vuex 中的 eduName 状态 let eduName = this.$store.state.eduName; alert(eduName); }, fun2() { // alert(this.msg) // 提交一个名为 setEduName 的 mutation 来更改 eduName 状态 this.$store.commit('setEduName', { eduName: this.msg }); } } } </script> <style> </style>
page2:
<template> <div> <h1>死亡丧彪</h1> {{eduName}} </div> </template> <script> export default { data() { return { msg: '默认值' } }, computed: { eduName() { // 从 Vuex store 中获取 eduName 的值 return this.$store.state.eduName; } } } </script> <style> /* 在这里添加组件的样式 */ </style>
到项目中src的router的index.js文件中配置路径,如下:
import page1 from '@/Views/vuex/page1' import page2 from '@/Views/vuex/page2'
{ path: '/vuex/page1', name: 'page1', component: page1 }, { path: '/vuex/page2', name: 'page2', component: page2 }
在src中的components的LeftNav.vue组件中编辑(增加)代码,如下:
<el-submenu index="idx_999" key="idx_999"> <template slot="title"> <span>vuex管理</span> </template> <el-menu-item index="/vuex/page1" key="idx_99901"> <span>页面1</span> </el-menu-item> <el-menu-item index="/vuex/page2" key="idx_99902"> <span>页面2</span> </el-menu-item> </el-submenu>
2.3 模块
在项目中创建store目录分别维护state/actions/mutations/getters/store
state.js:
export default{ eduName:'死亡60HZ的支配', aname:'', bname:'' }
mutations.js:
export default { setEduName: (state, payload) => { //state指的就是state.js文件中导出的对象 //payload就是vue文件传递过来的参数 // A.Vue name {a_name:this.name} // B.Vue name {b_name:this.name} // state.aname = payload.a_name; // state.bname = payload.b_name; state.eduName = payload.eduName; } }
getters.js:
export default { getEduName: (state) => { return state.eduname; } }
actions.js 先不写代码。
index.js:
import Vue from 'vue' import Vuex from 'vuex' import state from './state' import getters from './getters' import actions from './actions' import mutations from './mutations' Vue.use(Vuex) const store = new Vuex.Store({ state, getters, actions, mutations }) export default store
2.4 引用
在src中的main.js进行引用,如下:
import store from './store' /* eslint-disable no-new */ new Vue({ el: '#app', router, store, data(){ return{ Bus:new Vue() } }, components: { App }, template: '<App/>' })
然后取值操作在前面的page1页面中已经写完了,接下来我们进行效果展示,如下:
三、Vuex改变值
page1:
<template> <div style="padding: 60px;"> <h1>刘三金的羁绊</h1> <p>改变state中的值</p> 请输入你的初恋:<input v-model="msg" /> <button @click="fun1">获取state</button> <button @click="fun2">改变state</button> </div> </template> <script> export default { data() { return { msg: '默认值' }; }, methods: { fun1() { // 获取 Vuex 中的 eduName 状态 let eduName = this.$store.state.eduName; alert(eduName); }, fun2() { // alert(this.msg) // 提交一个名为 setEduName 的 mutation 来更改 eduName 状态 this.$store.commit('setEduName', { eduName: this.msg }); } } } </script> <style> </style>
执行结果如下:
四、Vuex异步&请求后台
4.1 Vuex同步异步详解
Vuex 是一个用于管理 Vue.js 应用程序状态的状态管理模式和库。在 Vuex 中,操作可以分为同步和异步操作,这两种操作类型在应用程序状态管理中起到不同的作用。以下是对 Vuex 同步和异步操作的详细解释:
- 同步操作:
同步操作是指立即执行并修改应用程序状态的操作。在 Vuex 中,这通常通过 mutations 来实现。Mutations 是用于修改状态的函数,它们必须是同步的,这意味着它们不应该包含异步代码。当你需要在应用程序中执行一些立即生效的状态变更时,同步操作是非常有用的。
- 异步操作:
异步操作是指可能需要一些时间来执行的操作,例如数据获取、网络请求、或其他需要等待的任务。在 Vuex 中,这通常通过 actions 来处理。Actions 是用于分发异步任务的函数,它们可以包含异步代码,例如异步 API 调用,然后在异步操作完成后提交 mutations 来修改状态。
异步操作适用于需要等待的任务,因为它们不会阻塞应用程序的其他操作,使得应用可以继续响应用户的输入。你可以在异步操作中使用异步 JavaScript 特性,如 Promises 或 async/await,来管理异步代码。
总结:
- 同步操作用于立即修改状态,是直接的、快速的操作。
- 异步操作用于处理需要等待的任务,例如网络请求、数据获取等。异步操作通过 actions 来触发,可以包含异步代码,并在异步操作完成后提交 mutations 来更新状态,以确保状态的一致性。
4.2 代码编写
在page1.vue组件中编写所有代码,page1代码如下:
<template> <div style="padding: 60px;"> <h1>刘三金的羁绊</h1> <p>改变state中的值</p> 请输入你的初恋:<input v-model="msg" /> <button @click="fun1">获取state</button> <button @click="fun2">改变state</button> <button @click="fun3">异步改变state</button> <button @click="fun4">请求后台</button> </div> </template> <script> export default { data() { return { msg: '默认值' }; }, methods: { fun1() { // 获取 Vuex 中的 eduName 状态 let eduName = this.$store.state.eduName; alert(eduName); }, fun2() { // alert(this.msg) // 提交一个名为 setEduName 的 mutation 来更改 eduName 状态 this.$store.commit('setEduName', { eduName: this.msg }); }, fun3() { this.$store.dispatch('setEduNameAsync', { eduName: this.msg }); }, fun4() { this.$store.dispatch('setEduNameAjax', { eduName: this.msg, _this:this }); } } } </script> <style> </style>
在page2.vue组件中编写所有代码,page2代码如下:
<template> <div> <h1>死亡丧彪</h1> {{eduName}} </div> </template> <script> export default { data() { return { msg: '默认值' } }, computed: { eduName() { // 从 Vuex store 中获取 eduName 的值 return this.$store.state.eduName; } } } </script> <style> /* 在这里添加组件的样式 */ </style>
在src的action.js中配置后台请求的地址,如下:
'VUEX_AJAX': 'vuex/queryVuex', //Vuex的后台异步请求
在src的store模块中编写actions.js,如下:
export default { setEduNameAsync: (context, payload) => { //context指的是Vuex的上下文 setTimeout(function() { context.commit('setEduName', payload); }, 10000); //十秒后执行 }, setEduNameAjax: (context, payload) => { let _this = payload._this; //this并不代表vue实例 let url = _this.axios.urls.VUEX_AJAX; let params = { resturantName:payload.eduName } _this.axios.post(url, params).then(r => { console.log(r); }).catch(e => {}) } }
4.3 效果展示
异步效果展示如下:
请求后台效果如下:
五、收获
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它可以帮助你管理应用程序的状态并确保状态的一致性,尤其在大型或复杂的应用程序中更为重要。使用 Vuex 进行状态管理可以带来许多好处,尤其是对于值的改变和异步操作。
- 一致性的状态管理: Vuex 提供了一个单一的状态树,即存放在一个地方的状态使得应用的所有组件可以访问和共享状态。这确保了应用的状态保持一致,避免了在不同组件中可能出现的状态不一致性问题。
- 易于跟踪和调试: 由于所有状态都集中在一个地方,因此更容易跟踪状态的变化,这对于调试和排查错误非常有用。你可以轻松地监控状态的变化,了解数据如何随时间变化。
- 中心化管理数据流: Vuex 将数据的流向、修改和维护集中到一个地方,而不是分散在多个组件中。这使得数据流变得可预测和易于理解,有助于应用程序的维护和扩展。
- 简化组件间通信: 通过 Vuex,组件之间的通信变得简单明了。你可以通过提交(mutations)和分发(actions)来修改状态,而不必通过多层嵌套的组件传递数据。
- 异步操作的便利性: 在 Vuex 中处理异步操作变得更为优雅。你可以在 actions 中发起异步操作,然后在操作完成后再提交(mutations)来更新状态。这使得管理异步行为更加清晰和有序。
- 适用于大型应用: 对于大型应用程序,特别是需要处理复杂状态和多组件交互的应用,使用 Vuex 可以更好地组织代码、分离关注点,从而使得应用程序更容易维护和扩展。
总的来说,Vuex 中的改变值和异步操作的使用可以让你更好地管理应用程序的状态,确保一致性、易于调试和拓展,并提高代码的清晰度和可维护性。
最后Vuex基础使用存取值+异步&请求后台就到这里,祝大家在敲代码的路上一路通畅!