热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

vuex请求变量后存储并使用_状态管理模式—Vuex如何使用?

Extract试想当我们在开发一个Vue应用程序时,如果在一个项目中频繁的使用组件传参的方式来同步data中的值,一旦项目结构变得复杂,管
4c388ef8dcb47847c598c67aa45315fc.png

Extract

试想当我们在开发一个Vue应用程序时,如果在一个项目中频繁的使用组件传参的方式来同步data中的值,一旦项目结构变得复杂,管理和维护这些数据将变得十分繁琐,为此,Vue为这些被多个组件共同使用的data提供了一个统一的管理工具---Vuex。

Vuex是专为Vue.js应用程序开发的状态管理模式,集中存储管理应用的所有组件的状态(数据),并以相同的规则保证状态以一种可预测的方式发生变化。

安装

可在项目目录下直接通过npm安装,其他安装方式详见Vuex安装。

npm install vuex --save

使用

首先需要创建一个store实例,引入你创建的所有modules:

目录结构/src|-main.js|-/store|-/modules|-index.js

// index.js
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
import team from './modules/team'
import product from "./modules/product";
import chat from "./modules/chat";
import notification from "./modules/notification";Vue.use(Vuex)export default new Vuex.Store({modules: {user,team,product,chat,notification},strict: true
})

main.js中,引入store实例并暴露出来:

import Vue from 'vue'import App from './App.vue'import store from './store'​export default new Vue({render: h => h(App),store}).$mount('#app')

State

State是Vuex的基本属性,称为单一状态树,如果熟悉Java面向对象编程的话,我们可以将其类比为成员变量:

public class User {//成员变量private String name;private Integer age;private String gender;}public class Users {private List users;}

const state = () => ({//Stateusers: [{name: ...,age: ...,gender: ..., },.........]
})

在Vue组件中获得Vuex状态可通过以下两种方式:

//方法一:在根实例中注册store选项,该实例会注入到根组件下的所有子组件中this.$store.state.name​//方法二:使用mapState辅助函数import { mapState } from 'vuex'​export default {// ...computed: mapState({// 箭头函数可使代码更简练count: state => state.count,​// 传字符串参数 'count' 等同于 `state => state.count`countAlias: 'count',​// 为了能够使用 `this` 获取局部状态,必须使用常规函数countPlusLocalState (state) {return state.count + this.localCount}})}​

Getter

getter的使用可类比为Java中的get方法。

public class User {//成员变量private String name;private Integer age;private String gender;}public class Users {private List users;//get方法public List getUsers() {return users;}}

//State
const state = () => ({users: [{name: ...,age: ...,gender: ..., },.........]
})//getter
const getters = {users: state => state.users,
}

如果仅仅如此,为何不直接获取state呢?因为有时候我们需要从state中派生出一些状态,例如对列表进行过滤,同样我们可与Java实现类比:

public class User {//成员变量private String name;private Integer age;private String gender;}public class Users {private List users;//get方法public List getUsers() {return users;}//返回18岁及以下用户对象public List getChildren() {List children &#61; new ArrayList<>;for (User item: this.users) {if (item.age <&#61; 18) {children.add(item)}}return children;}}

//State
const state &#61; () &#61;> ({users: [{name: ...,age: ...,gender: ..., },.........]
})//getter
const getters &#61; {users: state &#61;> state.users,//返回18岁及以下用户对象children: state &#61;> state.users,filter(user &#61;> user.age <&#61; 18),
}

在Vue组件中我们可以通过属性访问或者通过mapGetters来获取对象&#xff1a;

import { mapGetters } from &#39;vuex&#39;export default {computed: {...mapGetters([&#39;users&#39;,]),},methods: {printUsers() {//通过mapGetters访问console.log(this.users)//通过属性访问console.log(this.$store.getters.users)}}}

Mutation

提交mutation是更改Vuex的store中状态的唯一方法&#xff0c;Vuex中的mutation类似于事件&#xff1a;每个mutation都有一个字符串的事件类型&#xff08;type&#xff09;和一个回调函数&#xff08;handler&#xff09;。这个回调函数就是我们实际进行状态更改的方法&#xff0c;并且他会接受state作为第一个参数。

mutation的实际使用类似于Java中的set方法&#xff0c;是设置state值的唯一方式。

public class User {//成员变量private String name;private Integer age;private String gender;}public class Users {private List users;private Boolean status;//set方法public void setStatus() {this.status &#61; true; }}

//State
const state &#61; () &#61;> ({users: [{name: ...,age: ...,gender: ..., },.........],status: null,
})//mutation
const mutations &#61; {setStatus(state) {state.status &#61; true}
}

但不同于Java中set的使用方式&#xff0c;我们不能直接调用一个mutation handler&#xff0c;而是提交一个名为xxxmutation&#xff0c;触发相应的mutation handler执行具体的变更。

Users users &#61; new Users();
users.setStatus();

this.$store.commit("setStatus")

在Java中set函数可以传入参数进而变更成员变量。

public class User {//成员变量private String name;private Integer age;private String gender;}public class Users {private List users;private Boolean status;//set方法public void setStatus() {this.status &#61; true; }public void setUser(User user) {this.users.add(user);}}

调用set函数&#xff1a;

Users users &#61; new Users();users.setUser(newUser);

在Vuex中我们也可以通过提交载荷&#xff08;Payload&#xff09;的方式向store.commit传入额外的参数&#xff0c;即mutation的载荷。

//Stateconst state &#61; () &#61;> ({users: [{name: ...,age: ...,gender: ..., },.........],status: null,})//mutationconst mutations &#61; {setStatus(state) {state.status &#61; true},setUser(state, user) {state.users.push(user)}}

在组件中提交携带载荷的mutation&#xff1a;

this.$store.commit(&#39;setUser&#39;, user)

或者使用mapMutations映射出来&#xff1a;

import { mapMutations } from &#39;vuex&#39;​export default {methods: {...mapMutations([&#39;setUser&#39;,]),appendUser(user){this.setUser(user)},}}

综上看来&#xff0c;mutation的使用与set函数的目的是相同&#xff0c;但mutation在使用中最大的原则 --- 必须是同步函数。

mutation中混合异步调用会导致你的程序很难调试&#xff0c;当我们调用了两个包含异步回调的mutation来改变状态&#xff0c;我们无法知道什么时候回调以及哪个先回调&#xff0c;因此在Vuex中&#xff0c;mutation都是同步事务

Action

action类似于mutation是可“调用”的方法&#xff0c;两者不同点在于&#xff1a;

  • action提交mutation&#xff0c;而不直接变更状态&#xff1b;
  • action可以包含任意异步操作

//Stateconst state &#61; () &#61;> ({users: [{name: ...,age: ...,gender: ..., },.........],status: null,})​//actionconst actions &#61; {updateUser({commit}) {request({url: &#39;/user/getNewUser&#39;method: &#39;get&#39;}).then(res &#61;> {commit(&#39;setUser&#39;, res.data)})}}//mutationconst mutations &#61; {setStatus(state) {state.status &#61; true},setUser(state, user) {state.users.push(user)}}

这段代码中我们注册了一个简单的异步action&#xff0c;我们通过request向后端发送请求&#xff0c;请求新用户&#xff0c;然后我们在回调函数中提交mutation变更状态。

this.$store.dispatch(&#39;updateUser&#39;)

action同样可以通过提交载荷的方式进行分发&#xff1a;

//Stateconst state &#61; () &#61;> ({users: [{name: ...,age: ...,gender: ..., },.........],status: null,})​//actionconst actions &#61; {appendUser({commit}, user) {commit(&#39;setUser&#39;, user)}}//mutationconst mutations &#61; {setStatus(state) {state.status &#61; true},setUser(state, user) {state.users.push(user)}}

this.$store.dispatch(&#39;appendUser&#39;, newUser)

或者使用mapAction映射出来&#xff1a;

import { mapActions } from &#39;vuex&#39;​export default {// ...methods: {...mapActions([&#39;appendUser&#39;,]),test() {this.appendUser(user)}}}

Module

使用单一状态树&#xff0c;应用的所有状态都会集中到一个较大的对象&#xff0c;随着应用迭代变得越来越复杂&#xff0c;store对象会变得越来越臃肿。为了解决以上问题&#xff0c;Vuex允许我们将对象模块&#xff08;Module&#xff09;化&#xff0c;每个模块拥有自己的statemutationactiongetter甚至嵌套子模块。

const moduleA &#61; {state: () &#61;> ({ ... }),mutations: { ... },actions: { ... },getters: { ... }}​const moduleB &#61; {state: () &#61;> ({ ... }),mutations: { ... },actions: { ... }}​const store &#61; new Vuex.Store({modules: {a: moduleA,b: moduleB}})​store.state.a // -> moduleA 的状态store.state.b // -> moduleB 的状态

在默认情况下&#xff0c;模块内部的actionmutationgetter是注册在全局命名空间的&#xff0c;这样使得多个模块能够对同一mutationaction作出响应。

目录结构/src&#xff5c;-main.js&#xff5c;-/store&#xff5c;-/modules|-user.js|-team.js|-product.js|-chat.js|-notification.js&#xff5c;-index.js

user.js为例&#xff0c;让我们看一下一个完整的Module是怎样的。

//user.jsimport {request} from &#39;../../lib/network/request&#39;​//Stateconst state &#61; () &#61;> ({users: [{name: ...,age: ...,gender: ..., },.........],status: null,})​//actionconst actions &#61; {updateUser({commit}) {request({url: &#39;/user/getNewUser&#39;method: &#39;get&#39;}).then(res &#61;> {commit(&#39;setUser&#39;, res.data)})}}​//getterconst getters &#61; {users: state &#61;> state.users,//返回18岁及以下用户对象children: state &#61;> state.users,filter(user &#61;> user.age <&#61; 18),}//mutationconst mutations &#61; {setStatus(state) {state.status &#61; true},setUser(state, user) {state.users.push(user)}}​export default {state,getters,actions,mutations}

然后需要在/modules目录下的index.js中将各个module注册到store对象中&#xff1a;

//index.jsimport Vue from &#39;vue&#39;import Vuex from &#39;vuex&#39;import user from &#39;./modules/user&#39;import team from &#39;./modules/team&#39;import product from "./modules/product";import chat from "./modules/chat";import notification from "./modules/notification";​Vue.use(Vuex)​export default new Vuex.Store({modules: {user,team,product,chat,notification},//严格模式&#xff1a;无论何时发生了状态变更且不是由 mutation 函数引起的&#xff0c;将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。strict: true})​

然后在main.js中将store放进我们的Vue应用程序中&#xff1a;

//main.jsimport Vue from &#39;vue&#39;import App from &#39;./App.vue&#39;import store from &#39;./store&#39;​export default new Vue({render: h &#61;> h(App),store}).$mount(&#39;#app&#39;)

至此&#xff0c;这便是一个完整的Vuex的使用实例&#xff0c;虽然在Vue中我们也可以通过属性传递的方式在不同组件之间传递data&#xff0c;但是当同一个data需要被多个组件同时调用&#xff0c;数据的一致性便很难保证&#xff0c;Vuex的引入则很好的解决了这一问题&#xff0c;Vuex中状态的变化是全局的&#xff0c;是实时计算的&#xff0c;当我们getter的计算依托于多个state时&#xff0c;当我们提交了新的commit变更状态&#xff0c;相应的getter返回值也会变化&#xff0c;这让我们不用过多分心于数据的一致性。



推荐阅读
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • 本文介绍了如何使用vue-awesome-swiper组件,包括在main.js中引入和使用swiper和swiperSlide组件,以及设置options和ref属性。同时还介绍了如何在模板中使用swiper和swiperSlide组件,并展示了如何通过循环渲染swipes数组中的数据,并使用picUrl属性显示图片。最后还介绍了如何添加分页器。 ... [详细]
  • vue使用
    关键词: ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • Vue3中setup函数的参数props和context配置详解
    本文详细介绍了Vue3中setup函数的参数props和context的配置方法,包括props的接收和配置声明,以及未通过props进行接收配置时的输出值。同时还介绍了父组件传递给子组件的值和模板的相关内容。阅读本文后,读者将对Vue3中setup函数的参数props和context的配置有更深入的理解。 ... [详细]
author-avatar
为你空手的执着
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有