一:什么是vuex?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
大白话理解就是,这一部分为公共的东西,大家在其他的组件里面都可以调用,适用于中大型项目,小型项目用起来就显得有点冗余了。
二:vuex的安装
npm安装:
npm install vuex --save
三:在项目中使用
1、引入vuex
安装完成vuex后,会在项目的根目录下自动生成一个store的文件夹(基于vue-cli脚手架环境下),里面包含了一个index.js的文件。
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let store = new Vuex.Store({
state:{},
mutations:{},
action:{},
getters:{},
module:{}
})
export default store
2、完成整个项目的使用注册
项目的主入口js文件中加入:
import Vue from 'vue'
import App from './App.vue'
import store from './store/index.js' //引入vuex的js文件
Vue.config.productionTip = false
new Vue({
store, //注册后可以让我们的组件访问this.$store相关的api
render: h => h(App)
}).$mount('#app')
四:vuex的核心概念
1、State
state是用来定义共享状态的,其作用类似于组件中的data属性,存放公共数据的仓库。
let store = new Vuex.Store({
state:{
arr:[1,2,3,4]
}
})
我们可以将我们在其他组件都用得到的数据放到state这个仓库里面去,当我们在其他组件中要用到的时候,再取出来。我们获取这这些共享数据的方法是:
this.$store.state.arr //结果是[1,2,3,4]
2、Mutation
mutation是第二个属性,里面存放了所有的改变共享状态的方法,也就是说,所有的改变共享状态的方法,都需要放在这个属性里面。
比如,我们定义一个改变arr里面数据的方法
mutations:{ //存放了所有更改状态的方法
changeArr(state){
state.arr=[2,4,6,8,10] //注意:这里不要写成this.state.arr
}
3、Action
action类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。(记住,很重要)
- Action 可以包含任意异步操作。
比如我们如果在action里面进行一个异步请求,再将请求到的数据加入到state共享状态里面去,代码如下:
state:{
goodDate:[] //1.准备一个数组,用来存放请求到的数据
}
mutations:{
addDate(state,date){ //第二个参数表示传递进来的实参
state.goodDate=date //将传递来的实参赋值给准备好的数组
}
}
action{
axios.get("http://.......").then(res=>{
//假设这里的res就是我们请求到的数据,我们需要将这个数据赋值给goodDate这个数组里面
//这里我们就需要知道,action对共享状态的改变也是通过mutations进行的,所以,我们还是要调用mutations里面的方法,来实现赋值
//通过store.commit("方法名","参数")来实现
store.commit("addDate",res) //这样我们就把请求回来的数据赋值给了state里面的goodDate了。
})
}
我们在其他组件如何使用action?这样可以访问使用:
this.$store.dispatch("action方法名")
4、Getter
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
简单理解:getter的作用类似于组件的computed属性,可以对共享的状态进行操作的方法放到一起,并可以将处理后的数据缓存起来,只要共享状态没有发生改变,就不会重复执行。
比如,我们要在arr这个数组里面过滤出去数字2,不用getter我们也可以做到:
this.$store.state.arr.filter(item=>{item==2}) //通过this.$state.arr访问到arr数组
使用getter的写法如下:
getters:{
findDate(state){
return state.arr.filter(item=>{item==2})
}
}
当我们在其他组件中需要用到此方法的时候这样访问:
this.$store.getters.findDate
5、Module
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。
这句话的意思是:如果项目太大了,共享的状态太多了写在一起不利于维护,就要把他们分成每一个部分,每个部分都有自己的sate、action、getter、mutation、module五个部分,再将每个小部分组成一个大部分。打个形象的比喻:当皇上的国土面积太大了,每个地方的事情都皇帝管太累了,所以每个地方就安排地方官,每个地方官管理好了,整个国家也就管理好了,哪个地方出现了问题,就找地方官来解决,不会影响其他地方。
所以,我们的代码结构就发生了一点小小的变化:
我们可以在store的文件夹里面新建一个文件夹,在这个文件夹里面存放我们不同项目模块用到的共享数据。
cinemamodule.js文件里面存放影院模块的共享数据
const module = {
namespaced: true,//开启命名空间
state:{
cinemaList:[] //默认城市影院
},
getters:{ },
actions:{ },
mutations:{}
}
}
export default module
tabbarmodule.js文件里面存放导航模块的共享数据
const module = {
namespaced: true,//开启命名空间
state:{
arr:[1,4,7,2,5]
},
getters:{ },
actions:{ },
mutations:{}
}
}
export default module
index.js文件还是vuex主入口文件,里面的代码如下:
import Vue from 'vue'
import Vuex from 'vuex'
import moduleA from "./module/cinemamodule" //引入模块A
import moduleB from "./module/tabbarmodule" //引入模块B
Vue.use(Vuex)
let store = new Vuex.Store({
modules:{
moduleA:moduleA //注册moduleA
moduleB:moduleB //注册moduleA
})
export default store
我们如何取出我们需要的模块的数据呢?我们就要用到命名空间了。
namespaced: true,//开启命名空间(每个模块我们都加上这个行代码,就是开启了命名空间)
当我们在一个组件里面需要访问moduleA里面的数据的时候:
例如在组件创建之后初始化数据阶段
先引入绑定函数:
import {mapState} from "vuex"
computed(){
...mapState("moduleA", {
my- cinemaList:" cinemaList" //拿到了moduleA中的sate数据cinemaList
})
}
或者这样写:
computed(){
...mapState("moduleA", ["cinemaList"])
}
我们在组件中使用的时候,直接this.cinemaList就可以获取到了。
mapState, mapGetters, mapActions 和 mapMutations是命名空间的**绑定函数**,绑定函数在使用之前都需要解构引入。
…(三个点运算符)是ES6的解构赋值法,因为mapState的返回值是一个对象,如果我们在一个对象里面使用此方法,就是在对象里面套对象,这样会产生语法错误。因此要将其解构出来,我们把它理解为固定写法即可。
笔者水平有限,理解错误之处,还请大家指出!更多详细内容,请参考vuex官方文档。