目录
Vuex
1、Vuex的五个属性
2、Vuex工作原理
3、Vuex的使用
在html文件中使用
辅助函数
模块化modules和命名空间namespaced
在vue-cli脚手架中使用
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
Vuex是一个状态管理模式,也叫状态机,将组件共享的数据放到状态机中统一管理,组件想拿数据可以从自己的数据模型中拿,也可以从仓库中拿,可以把vuex理解成一个仓库。
假设A组件想要拿B组件里面的数据,那就把A组件和B组件的数据放到Vuex中,A组件想要获取B组件数据从vuex中拿,B组件想要获取A组件的数据也从Vuex拿。
{
//state 维护的是公共状态(数据),类似Vue中的data
state: {},
//getters 处理state中的数据并返回新数据,类似计算属性computed
getters: {},
//mutations 突变,修改state的唯一方式,只能做同步操作
mutations: {},
//actions 动作,处理异步操作,获取后台响应,提交数据给突变mutations
actions: {},
// 状态机可以有多个,modules用来存放各模块的状态机
modules: {}
}
vuex三个主要的属性:state、mutations、actions
当我们声明了一个状态机并将其注入Vue实例中,那么Vue实例上就会存在一个$store属性,该属性上有dispatch和commit等方法。
分析上图:
Vue组件将需要执行的方法通过dispatch方法派发给Actions执行,但是Actions不会去执行该方法,于是它又通过commit方法提交该方法给Mutation来执行,Mutation执行完后,将处理完的数据给State,然后State重新渲染数据到页面。
注意:当Vue组件需要操作的数据不需要通过网络请求得到时,可以跳过actions,直接使用commit方法提交给mutations处理。
1、通过CDN引入Vuex
Vuex是Vue的一个插件,使用时需要安装
2、声明状态机
let store = new Vuex.Store(
{
//state 维护的是公共状态,类似Vue中的data
state: {},
//getters 处理state中的数据并返回新数据,类似计算属性computed
getters: {},
//mutations 突变,修改state的唯一方式,只能做同步操作
mutations: {},
//actions 动作,处理异步操作,获取后台响应,提交数据给突变mutations
actions: {}
}
)
3、将状态机注入Vue实例
let vm = new Vue({
// 将状态机注入Vue实例
store,
el: "#app",
data: {}
})
此时可以打印Vue实例中的$store看一下:
console.log(vm.$store)
因此我们可以在插值语法中使用 $store.state.xxx 和 $store.getters.xxx 访问state中的数据和getters中的方法。
例子:
Document
{{$store.state.msg}}
{{$store.getters.MSG}}
{{$store.state.sum}}
Vuex提供的组件辅助函数有mapState、mapGetters、mapActions、mapMutations,它们存在Vuex对象上,使用时可以使用Vuex.mapState的方式调用,也可以将它们从Vuex中解构出来使用:
let { mapState, mapGetters, mapActions, mapMutations } = Vuex
1、mapState方法:用于帮助映射 state 中的数据为计算属性
computed:{
// msg(){
// return this.$store.state.msg
// },
// sum(){
// return this.$store.state.sum
// }
//-----------------------------------------------------
// 借助mapState函数生成上述计算属性
// mapState返回一个对象,我们需要使用扩展运算符将它们展开
// 1、对象写法
...mapState({msg:'msg',sum:'sum'})
// 2、数组写法
...mapState(['msg','sum'])
},
// 测试,看一下mapState返回值
created(){
let a = mapState({msg:'msg',sum:'sum'})
console.log(a); //返回一个对象,对象中有msg、sum方法
},
使用了mapState方法之后,我们在插值语法直接使用{{msg}}、{{sum}}即可,不需要写成:{{$store.state.msg}}、{{$store.state.sum}},同理mapGetters方法也一样。
2、mapGetters方法:用于帮助映射 getters 中的数据为计算属性
computed:{
// MSG(){
// return this.$store.getters.MSG
// }
//------------------------------------------------------
// 借助mapGetters函数生成上述计算属性
// 1、对象写法
...mapGetters({MSG:'MSG'})
// 2、数组写法
...mapGetters(['MSG'])
},
3、mapActions方法:用于帮助生成与 actions 对话的方法,即包含$store.dispatch(xxx)的函数
methods:{
// foo(){
// this.$store.dispatch('add', this.n)
// }
//--------------------------------------------
// 借助mapActions函数生成上述foo方法
// mapActions返回一个对象,我们需要使用扩展运算符将它们展开
// 1、对象写法
...mapActions({foo:'add'}),
// 2、数组写法 (注意:需要对象的属性名和属性值一样才能写成下面的数组形式)
...mapActions(['foo'])
}
4、mapMutations方法:用于帮助生成与 mutations 对话的方法,即包含$store.commit(xxx)的函数
methods:{
// foo(){
// this.$store.commit('ADD', this.n)
// }
//--------------------------------------------
// 借助mapMutations函数生成上述foo方法
// mapMutations返回一个对象,我们需要使用扩展运算符将它们展开
// 1、对象写法
...mapMutations({foo:'ADD'}),
// 2、数组写法 (注意:需要对象的属性名和属性值一样才能写成下面的数组形式)
...mapMutations(['foo'])
}
注意:使用 mapActions 和 mapMutations 时,若需要传递参数,那么参数要在模板绑定事件的时候传参。
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块,每个模块拥有自己的 state、mutation、action、getter,甚至是嵌套子模块。namespaced表示设置命名空间。
Vuex中的modules属性用来存放各个模块的状态机。
let aModule = {
// 开启命名空间
namespaced: true,
state:{},
getters:{},
actions:{},
mutations:{}
}
let bModule = {
namespaced: true,
state:{},
getters:{},
actions:{},
mutations:{}
}
let store = new Vuex.Store({
modules:{
a:aModule,
b:bModules
}
})
(1)组件中读取state中数据
// 方式一:自己读取
this.$store.state.a.xxx
// 方式二:使用mapState读取 表示后面数组里面的属性是a模块的
...mapState('a',['xxx1','xxx2','xxx3'])
(2)组件中读取getters中的数据
// 方式一:自己读取
this.$store.getters['a/xxx']
// 方式二:使用mapGetters读取 表示后面数组里面的属性是a模块的
...mapGetters('a',['xxx1','xxx2','xxx3'])
(3)组件中调用dispatch
// 方式一:自己直接dispatch
this.$store.dispatch('a/xxx',需要传递的数据)
// 方式二:使用mapActions读取
...mapActions('a',['xxx1','xxx2','xxx3'])
(4)组件中调用commit
// 方式一:自己直接commit
this.$store.commit('a/xxx',需要传递的数据)
// 方式二:使用mapMutations读取
...mapMutations('a',['xxx1','xxx2','xxx3'])
写个小案例:当我们点击登录的时候会获取到一个token值,这个token值其他组件也需要使用,因此我们可以把token值存在vuex中,供所有的组件使用。
1、安装vuex
注意:vuex4版本以上只能在vue3中使用,vue2使用vuex3版本,安装时如果不指定版本,会安装最新版本的vuex
npm i [email protected]
2、在src下新建一个文件夹store,然后在store文件夹下再新建一个文件夹login,存放登录相关的状态机
src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
// 引入登录状态机
import login from '../store/login/login';
Vue.use(Vuex);
export default new Vuex.Store({
state:{},
getters:{},
mutations:{},
actions:{},
modules:{
login
}
})
src/login/login.js
import axios from 'axios';
// 这是我登录状态机配置对象
export default {
// 开启命名空间
namespaced: true,
state: {
token: localStorage.getItem('token') || ""
},
gettes: {},
mutations: {
SET_TOKEN(state, payload) {
state.token = payload;
// 持久化储存
localStorage.setItem('token', payload)
}
},
actions: {
async login({commit}, payload) {
// 发送异步请求
let res = await axios.post('登录接口地址', payload)
// console.log(res);
commit('SET_TOKEN', res.data.data.token)
}
}
}
3、在src下新建文件夹pages,存放组件
login.vue
登录页面-----
user.vue
用户页面--{{token}}