当前位置:   article > 正文

关于Vuex的简单理解和使用_vuex的理解和使用

vuex的理解和使用

1、什么是Vuex?

在使用vue作为框架的前端项目开发中,我们经常会碰到Vuex,那么Vuex到底是什么东西呢?

根据官方文档给出的解释是:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

简单来说,Vuex就是一个状态管理的库,或者说是一个用来存放组件公共数据的仓库。

2、为什么要使用Vuex

要了解为什么要使用Vuex,那么我们就需要先来了解vue项目中组件之间的传参方式

2.1、组件之间的传参方法

父组件向子组件传参:

// 父组件传递参数
<template><!-- 引入子组件 --><son :fatherData="fatherData"></son>
</template>

<script> import Son from "./son.vue";
export default {components: {Son,},data() {return {fatherData: "父组件的数据"};},
}; </script>

// 子组件接收参数
<template><div>{{ fatherData }}</div>
</template>

<script> export default {// 接收父组件传递的值props: {fatherData: {type: String,required: true,},},
}; </script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

子组件向父组件传参:

// 父组件
<template><!-- 引入子组件 --><div><son @getData="getSonData"></son><div>{{sonData}}</div></div>
</template>

<script> import Son from "./son.vue";
export default {components: {Son,},data() {return {sonData:''}},methods: {// 自定义的调用方法的参数就是子组件传递过来的数据getSonData(value) {this.sonData = value}}
}; </script>

// 子组件
<template><div><button @click="toFather">子向父传参</button></div>
</template>

<script> export default {data() {return {sonData: '子组件的数据'}},methods: {// 使用$emit来触发父组件中的自定义事件,将子组件的数据通过$emit传递给父组件toFather() {this.$emit('getData',this.sonData)}}
}; </script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

组件之间跳转的传参方法(示例由组件A跳转到组件B):

// A组件
<template><button @click="toB">跳转到B页面</button>
</template>

<script> export default {data() {return {aData: "A页面的数据",};},methods: {toB() {// 在页面跳转时,通过query传递数据this.$router.push({path: "/B",query: { aData: this.aData },});},},
}; </script>

// B组件
<template><div>{{ bData }}</div>
</template>

<script> export default {data() {return {bData: "",};},created() {this.bData = this.$route.query.aData;},
}; </script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

从上面三种组件之间传参的方式我们可以看出,组件与组件之间传递参数实现数据共享,那么组件之间需要有一定联系,要么是父子组件,要么是有跳转的关系,才能实现数据的共享。可是在完全没有联系的组件之间,他们如何实现数据的共享呢?

要想实现完全没有联系的组件之间数据共享,我们需要先思考一个问题,什么样的数据,需要同时在几个没有联系的组件中去使用呢?

2.2、 数据共享的情景

在项目开发中,我们经常会碰到一种情景,比如说一个系统,在用户登录之后,后端会将该用户的一些数据返回给前端,如用户名,token等,而这些用户数据往往不止在一个页面中使用,可能涉及到多个相互没有联系的组件,那么在这种时候,我们就需要使用到Vuex。

3、Vuex的使用

对于一个插件的使用,我们首先需要看对应的官方文档:Vuex 是什么? | Vuex (vuejs.org)。根据文档,接下来我们来一起理解Vuex。

在Vuex中有五个属性,分别为state,getters,mutations,actions,modules,下面我们将从这五个属性来学习Vuex。

3.1、state属性:

从上面的概念我们知道,Vuex是用来存放一些共享的数据,实现状态管理的一个插件,那么,我们的这些数据要放在那里呢?

在项目目录下,我们可以找到一个名为store的文件夹,文件夹中存放一个index.js的文件

我们之后关于Vuex的一些操作,基本都会在这个文件夹下的文件中实现。

首先我们来看一下index.js文件中都有些什么

// 导入vue
import Vue from 'vue'
// 导入Vuex
import Vuex from 'vuex'
// 注册Vuex组件
Vue.use(Vuex)

// 导出Vuex.Store
export default new Vuex.Store({state: {},getters: {},mutations: {},actions: {},modules: {}
}) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

我们可以看到,index.js中的内容基本和其他的插件的使用方式一样,我们主要看Vuex.Store中的内容,我们可以看到前面讲到的五个属性就是在Vuex.Store中,而我们的数据,就会放在state中。那么,怎么使用这个数据呢,我们使用文档中举的例子来示例。

首先,我们需要在state中加入我们要在其他组件中使用的数据

// store/index.js
export default new Vuex.Store({state: {// 添加一个变量numnum: 0},
}) 
  • 1
  • 2
  • 3

在store中添加了数据之后,我们需要到对应的组件中使用

组件A中使用

<template><div>{{$store.state.num}}</div>
</template> 
  • 1
  • 2

组件B中使用

<template><div>{{num}}</div>
</template>

<script> import { mapState } from 'vuex'
export default {computed: {...mapState(['num'])}
} </script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里我举例了两种组件调用state中数据的方法,文档中还提到了其他的方法,可以自行查看。

到这里我们发现,我们已经实现了将数据存放在一个地方,可以供多个不相关的组件一起调用,那么好像数据共享就完成了一部分,但是我们也知道,前端的数据往往不是单纯地进行展示,而是需要进行操作,那么,对于Vuex中的数据,我们要怎么进行操作呢?

按照前端开发的思路,原则上只要我们获取到数据,好像就可以对数据进行操作了,我们既然通过store.state.num可以获取到num,那么对store.state.num可以获取到num,那么对store.state.num可以获取到num,那么对store.state.num进行操作就可以了,按这个思路,我们可以看看是否成功?

<template><button @click="add">num加一</button>
</template>

<script> export default {methods: {add() {this.$store.state.num++;}}
} </script> 
  • 1
  • 2
  • 3
  • 4
  • 5

通过试验,我们发现,页面展示的数据确实达到了想要的效果,但是通过Vue开发者工具,我们发现,Vuex的state一直都没有改变

很显然,我们不能直接通过$store.state.num来改变数据,那么我们到底需要怎么样改变数据呢?

3.2、mutations属性:

通过看Vuex的文档,我们可以在mutations属性介绍中发现这样一句话:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。那么根据这句话,我们就可以知道,想要修改num,必须提交mutation,根据文档的使用方法,我们更改一下代码:

<template><button @click="add">num加一</button>
</template>

<script> export default {methods: {add() {this.$store.commit('addNum')}}
} </script> 
  • 1
  • 2
  • 3
  • 4
  • 5
// store/index.js
export default new Vuex.Store({state: {// 添加一个变量numnum: 0},mutations: {addNum(state) {state.num++;}},
}) 
  • 1
  • 2
  • 3

结果也符合预期:

那么到这里,数据的展示和操作好像都已经完成了,可是我们发现,还有三个属性都没有用到,那么这三个属性又有什么样的用处呢?

3.3、actions属性:

我们知道,在实际的项目开发中,我们会碰到很多异步操作,比较常见的就用axios请求,定时器等,那么我们对Vuex中的数据进行异步操作时是不是还是使用mutations呢?

很显然,大家看目录到这里,就知道对Vuex中的数据进行异步操作是要用到actions的,但是我们在学习mutations的时候有了解到更改 Vuex 的 store 中的状态的唯一方法是提交 mutation,那么actions是如何提交mutation的呢?

export default new Vuex.Store({state: {// 添加一个变量numnum: 0},mutations: {addNum(state) {state.num++;}},actions: {addNum(context) {setTimeout(() => {context.commit('addNum')},1000)}},
}) 
  • 1
  • 2
<template><div><button @click="add">num加一</button><button @click="delayed">延时加1</button></div>
</template>

<script> export default {methods: {add() {this.$store.commit("addNum");},delayed() {this.$store.dispatch("addNum");},},
}; </script> 
  • 1
  • 2
  • 3
  • 4
  • 5

我们可以看到在action中,有一个addNum方法接收了一个context参数,然后再方法中有一个定时器,定时器中通过conntext.commit调用了addNUm,看到.commit我们就会看到调用mutations时用的就是**this.store.commit(′addNum′),∗∗那是不是达标,action接收的那个context参数就是this.store.commit(‘addNum’),** 那是不是达标,action接收的那个context参数就是this.store.commit(′addNum′),∗∗那是不是达标,action接收的那个context参数就是this.store呢?我们使用console.log分别输出this.$store和context

在控制台中,我们可以看到,这两者有类似的属性,但是又不完全相同,但是,两者都有着同样的方法,那么就有可能是,context与store存在着某些联系,可以通过context.commit提交mutations。根据文档给出的解释是,Action函数接收了一个与store实例具有相同方法和属性的context对象,使我们可以通过context.commit来提交mutations。

3.4、modules属性:

modules的中文意思是模块,那么见名思意,我们可以大致理解为modules属性就是用来存放模块的。那么,在存放模块之前,就意味着我们需要现有模块。

在Vuex中,是允许我们将store分割成模块,每个模块拥有自己的state,mutations,action,getters甚至是modules,那么我们想象一下,为什么我们需要将store分割成模块呢?

我们知道,组件化开发,可以将根据功能划分组件,然后再讲组件整合在一起,这样既有利于我们分工,也增加了代码的复用性和便于后期的维护。而将store显然也是出于这样的考虑,我们知道,在一个大型的项目,需要进行状态管理的数据往往不是一两个变量,而是一个很复杂庞大的数据,如果我们将这些数据全部写到index.js文件中,那么整个文件就会显得冗余,而是可读性很低,那么这时候就需要我们将这些数据分割成不同的模块。

// store/index.js
export default new Vuex.Store({state: {},mutations: {},actions: {},modules: {user,menu,tab}
}) 
  • 1
  • 2
  • 3

例如这样,我们就可以根据我们的需要,将user和menu的数据分割成一个模块,这样store/index.js这个文件就会显得很精简,而且也便于我们的更改。

3.5、getters属性:

getters这个属性主要用于对state中的数据进行一些数据处理,在某种程度上来说,比较像组件中的computed。这里的数据处理和上面的mutations的数据操作并不是同一个意思。

getters的数据数据处理是指将state处理之后在组件中展示,而mutations则是指在触发某些事件之后对数据进行对应的操作。

举个例子,我们现在state中的num是0,我们知道在点击事件提交mutations之后num会加1,但是我们现在希望在增加多一个变量的前提下,组件A展示的是1,组件B展示的是0,那么在这个时候,我们就需要用到getters对state的num进行数据处理

export default new Vuex.Store({state: {// 添加一个变量numnum: 0},getters: {getAddNum(state) {return state.num+1} },mutations: {addNum(state) {state.num++;}},actions: {addNum(context) {console.log("context",context)setTimeout(() => {context.commit('addNum')},1000)}},
}) 
  • 1
  • 2

组件A:

<template><div>{{$store.getters.getAddNum}}</div>
</template> 
  • 1
  • 2

这样,我们就可以达成我们的目的:

4、总结

Vuex的使用还有很多需要注意的地方,本文只是简单的理解Vuex的几个属性的使用方法。

需要注意的地方是:由于Vuex的版本升级,很多地方进行了修正(详情可以查看官方文档),本文的代码是基于"vuex": "^3.4.0"版本的,如果按本文的代码练习出现错误,请寻找对应的Vuex版本代码进行学习。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/257012
推荐阅读
相关标签
  

闽ICP备14008679号