前言
在大型的Vue.js应用中,我们经常需要共享状态和进行复杂的状态管理。Vuex是一个专为Vue.js设计的状态管理库,提供了一种集中式的方式来管理应用的所有组件的状态。本文将详细介绍Vuex的使用方法,包括参数值的获取、修改,以及异步数据处理。
一、Vuex简介
1.Vuex是什么
Vuex是一个专为Vue.js应用设计的状态管理库。它提供了一种集中式的方式来管理应用的所有组件的状态,并且使得状态的变化变得可追踪、可维护。通过使用Vuex,我们可以将共享的数据以及与数据相关的逻辑统一管理,从而提高代码的可读性和可维护性。
在Vue.js应用中,组件之间的通信可以通过props和事件来实现。然而,当应用规模较大时,组件之间的状态交互变得更加复杂,而这些状态往往需要在多个组件之间共享和同步。这时,使用Vuex可以让我们更好地解决这些问题。
2.Vuex的核心概念
- State(状态):存储应用的所有状态数据,类似于组件中的data选项。但是与组件的data不同的是,state存储的状态是全局共享的。
- Getter(获取器):用于对state进行计算或过滤,类似于组件中的computed属性。Getter可以对state进行派生,将其转换成其他形式的值,便于组件使用。
- Mutation(突变):用于修改state的值,必须是同步函数。将组件中的某个操作导致的状态变更封装成mutation,通过提交(commit) mutation来改变state的值。
- Action(行动):用于处理异步操作或复杂的业务逻辑,并提交(commit) mutation来改变state的值。Action可以包含任意异步操作,例如网络请求、定时器等。组件中通过dispatch action来触发异步操作。
- Module(模块):将大型应用分割成更小的模块,每个模块拥有自己的state、getter、mutation和action,以实现更好的代码组织和维护。
3.使用Vuex的好处
- 集中式管理:通过将状态集中管理,使得状态的变化更加可追踪和可维护。
- 组件通信:Vuex提供了一种在组件间共享状态的机制,简化了组件之间的通信过程。
- 开发效率:通过统一管理状态和逻辑,减少了重复的代码,提高了开发效率。
- 调试工具支持:Vue开发者工具提供了对Vuex的调试支持,方便我们查看和追踪状态的变化。
- 优化性能:通过使用Getter对state进行缓存,避免了重复计算成本,提高性能。
- 可扩展性和可维护性:在大型应用中,模块化开发是必要的,使用Vuex可以有序地维护模块之间的关系,使得代码更易于维护和扩展。Vuex的状态管理机制也可以避免因为不同模块数据交互不当导致应用整体性能问题。
4.Vuex执行流程
- 创建Vuex Store:首先,在Vue.js应用中创建一个Vuex store实例。这个实例将会承载应用的所有状态和相关的逻辑。我们可以在主入口文件(通常是main.js)中创建store实例,并将其注入到根Vue实例中。
- 定义状态(State):在Vuex的store中定义state,即应用的所有状态数据。这些数据是共享的,可以被多个组件访问和修改。
- 使用Getter获取状态:Getter用于对state进行计算或过滤操作,类似于组件中的computed属性。Getter可以对state进行派生,将其转换成其他形式的值,方便组件使用。
- 提交Mutation修改状态:Mutation用于修改state的值,必须是同步函数。在store中定义mutation,然后通过commit方法提交(mutate)一个mutation来改变state的值。Mutation是Vuex中唯一修改state的方式,这样做可以保证状态变更的追踪性。
- 分发Action处理异步操作:Action用于处理异步操作、复杂业务逻辑或批量的mutation。在store中定义action,然后通过dispatch方法触发一个action的执行。Action可以包含任意异步操作,例如网络请求、定时器等。在action中可以根据需要触发一个或多个mutation来改变state的值。
- 组件中使用状态:在Vue组件中,可以通过computed属性或者在template中使用{{}}表达式来获取state或者Getter的值。当需要修改state时,通过commit一个mutation或dispatch一个action来触发状态的变化。
- 模块化管理:对于大型应用,可以将store分割成多个模块,每个模块拥有自己的state、getter、mutation和action。这样可以更好地组织和维护代码。
二、Vuex的使用步骤
1.安装Vuex
npm i -S vuex@3.6.2
在package.json中可以看到Vuex
2.创建store模块,分别维护state/actions/mutations/getters
注:在store/index.js文件中新建vuex的store实例,并注册引入各大模块
3.使用Vuex存储值,获取值和改变值
1.state.js---存值
export default{ name:'美猴王' }
2.mutations.js---改变值
export default{ setName:(state,payload)=>{ //state指的是state.js文件中导出的对象 //payload是vue文件传递过来的参数 state.name=payload.name } }
3.getters.js---取值
export default{ getName:(state)=>{ //state指的是state.js文件中导出的对象 return state.name; } }
4.store/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
5.在main.js中导入并使用store实例
6.在views下创建vuex目录并创建One.vue组件
<template> <div> <h1>我是number one</h1> 猴名:<input v-model="msg"/> <button @click="fun1">获取vuex的值</button> <button @click="fun2">改变vuex的值</button> </div> </template> <script> export default{ data(){ return{ msg:'吉吉' } }, methods: { fun1(){ let name= this.$store.state.name; alert(name) }, fun2(){ this.$store.commit('setName',{ name:this.msg }) } } } </script> <style> </style>
效果演示
7.跨页面获取值
<template> <div> <h1>我是number Two</h1> {{name}} </div> </template> <script> export default { computed:{ name(){ // return this.$store.state.name; return this.$store.getters.getName; } } } </script> <style> </style>
注:return this.$store.state.name;打破了封装性
return this.$store.getters.getName;用该方法也同样可以获取值
效果演示
4.通过异步实现获取和改变值
action.js:异步改变值
export default { setNameSynac:(context,payload) => { //context指的是vuex的上下文 setTimeout(function(){ context.commit('setName',payload) },6000) } };
One.vue组件
<template> <div> <h1>我是number one</h1> 猴名:<input v-model="msg" /> <button @click="fun1">获取vuex的值</button> <button @click="fun2">改变vuex的值</button> <button @click="fun3">异步改变vuex的值</button> </div> </template> <script> export default { data() { return { msg: '吉吉' } }, methods: { fun1() { let name = this.$store.state.name; alert(name) }, fun2() { this.$store.commit('setName', { name: this.msg }) }, fun3() { this.$store.dispatch('setNameSynac', { name: this.msg }) } } } </script> <style> </style>
效果演示
5.通过异步实现发送Ajax到后端请求
后端代码
package com.ctb.ssm.controller; import com.ctb.ssm.util.JsonResponseBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.text.SimpleDateFormat; import java.util.Date; @RestController @RequestMapping("/vuex") public class VuexController { @RequestMapping("/queryVuex") public JsonResponseBody<?> queryVuex(HttpServletRequest request) { String resturantName = request.getParameter("resturantName"); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String date = sdf.format(new Date()); try { System.out.println("模拟异步情况,睡眠5秒,不能超过10秒,axios超时时间设置的是10秒!"); Thread.sleep(5000); System.out.println("睡醒了,继续..."); } catch (Exception e) { e.printStackTrace(); } return new JsonResponseBody<>(resturantName + "-" + date,true,0,null); } }
src/api/action.js配置后端请求
'VUEX': '/vuex/queryVuex', //Vuex后端异步获取
src/store/action.js异步发送Ajax请求到后端
setNameAjax: (context, payload) => { let _this=payload._this let url = _this.axios.urls.VUEX let params = { resturantName: payload.name } _this.axios.post(url, params).then(r => { console.log(r) }).catch(r => { }); }
One.vue组件
<template> <div> <h1>我是number one</h1> 猴名:<input v-model="msg" /> <button @click="fun1">获取vuex的值</button> <button @click="fun2">改变vuex的值</button> <button @click="fun3">异步改变vuex的值</button> <button @click="fun4">异步发送Ajax请求到后端</button> </div> </template> <script> export default { data() { return { msg: '吉吉' } }, methods: { fun1() { let name = this.$store.state.name; alert(name) }, fun2() { this.$store.commit('setName', { name: this.msg }) }, fun3() { this.$store.dispatch('setNameSynac', { name: this.msg }) }, fun4() { this.$store.dispatch('setNameAjax', { name: this.msg, _this: this }) } } } </script> <style> </style>
效果演示
注:
1.在store/action.js中this并不代表vue实例,所以我们需在vue组件中将this传递过去
2.异步相应时间超时内容不会显示,我们可以尽量避免时间过长或者可以修改响应后端超时的时间。
6.同步和异步的区别
- 同步操作是按顺序执行的,一般用于执行时间较短的操作。而异步操作则是交由系统底层处理,程序继续往下执行。一般用于执行时间较长或需要等待的操作。
- 同步操作会阻塞主线程的执行,而异步操作不会阻塞主线程的执行。
- 异步操作不需要等待操作完成才能开始下一步操作,而同步操作需要等待操作完成后才能进行下一步操作。