Vuex简介:
    Vuex是一个专门为Vue.js应用程序开发的状态管理模式
        它采用集中存储管理应用组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化;
        Vuex也集成到Vue的官方调试工具Devtools,提供了诸如零配置的time-travel调试、状态快照导入导出等高级调试功能
如果我们不使用Vuex,那么就需要定义全局变量,但定义的全局变量不在vue的响应式系统中,我们还需要给其设置相应,很复杂,所以就有了Vuex
设置全局变量:

	const shareObj = {
		name:'pshdhx'
	}
	Vue.prototype.shareObj = shareObj;

这样不是响应式的;
那么Vue管理什么状态呢?
    在开发中,往往会遇到多个状态,在多个界面之间共享的问题;
    比如用户的登录状态,用户名称,头像,地理位置信息等;
    比如商城的收藏,购物车中的物品;
这些状态信息,我们都可以放在统一的地方,对其进行保存和管理,而且他们还是响应式的;
1、首选对Vue项目引入Vuex的包
    npm install vuex --save
2、初步建立Vuex的目录结构
    在src文件夹下新建index.js
3、在index.js中引入注册使用vuex

import Vue from 'vue'
	import Vuex from 'vuex'
	//安装vuex
	Vue.use(Vuex);
	//创建对象
	const store = new Vuex.Store({
		state:{},
		mutations:{},
		getters:{},
		actions:{},
		modules:{}
	})
	//导出store对象
	export default store

4、在main.js中注册

import store from '/store'
	new Vue({
		el:'#app',
		store,
		render:h=>h(App)
	})

初使用vuex-State,Mutations

state是存储状态变量的部分,如果想要对其进行修改,那么必须要经过Mutations(存储同步请求方法的模块),这样用Devtools插件才能够看到state中值的变化 ,方便遇到错误时调试;如果直接进行修改state中的值,那么Devtools里边的状态变量不会进行响应,只会在页面上进行响应,造成页面上的值与Devtools中的值不一致的后果,影响开发人员判断;

为什么绕一圈,才能修改state中的值,因为Actions中定义的是异步方法,Mutations中定义的是同步方法,不同的方法调用方式不同,但是最终都是通过调用Mutations中的方法进而修改State中的值;

初步使用vuex-state模块
index.js
const store = new Vuex.Store({
	state:{
		count:100
	},
	mutations:{
		increment(state){
			state.count++
		},
		decrement(state){
			state.count--
		}
	}
})
App.vue
	<button @click="addition">+</button>
	<button @click="subtration">-</button>
<script>
	methods:{
		addition(){
			this.$store.commit('increment')
		},
		subtration(){
			this.$store.commit('decrement')	
		}
	}
</script>

Vuex的核心概念

State,Getters,Mutations,Actions,Modules

State的单一状态

  我们知道,在国内我们有很多信息需要被记录,比如上学时的个人档案,工作后的社保记录,公积金记录等;

  这些信息被分散在很多地方进行管理,有一天当你需要办理户口迁入的时候,你会发现你需要到各个对应的工作地点去打印、盖章各种资料信息,最后到一个地方提交证明你的信息无误;

而单一的状态管理就避免了这种情况,所以所有的状态变量都放在了State中进行管理;

Getters基本使用

const store = new Vuex.Store({
	State:{
		students:[
			{id:110,name:'pshdhx1',age:18},
			{id:111,name:'psdhhx2',age:20},
			{id:112,name:'pshdhx3',age:22},
			{id:113,name:'pshdhx4',age:25},
		]
	}
})

此时我们要过滤出age>20的对象;

computed:{
	moreThan20(){
		return this.$Store.state.students.filter(age=>age>=20).length;
	}
}
//如果是这样,那么在每个页面中都要定义该计算方法,但是如果定义在vuex中,那么就很方便了;
getters:{
	moreThan20(state){
		return state.students.filter(s => s.age>20).length;
	}
}
//getters中方法的参数中有state,就是index.js中的state
实际上getters中可以返回函数
moreAgeStu(state){
	return function(age){
		return state.students.filter(s=>s.age>age)
	}
	// return age => {return state.students.filter(s=>s.age>age)}
}
//App.vue
<button @click="this.$store.getters.moreAgeStu(20)"></button>

Mutations状态更新

Vuex的store状态更新的唯一方式:提交mutation

Mutation主要包含两部分:

  字符串的事件类型:type

  一个回调函数handler,该回调函数的第一个参数就是state

Mutations的定义方式
mutations:{
    state.count++    
}
通过mutation进行更新
increment:function(){
    this.$store.commit('increment');
}
App.vue
methods:{
    addCount(count){
        this.$store.commit('incremntCount',count);
    }
}
mutations:{
    incrementCount(state,count){
        state.counter+=count
    }
}
methods:{
    addStudent(){
        count stu = {id:114,name:'pshdhx5',age:'23'}
        this.$store.commit('addStudent',stu);
    }
}
addCount(count){
    this.$store.commit({
        type:'incrementCount',
        count
    });
}
//这时传递的是count对象;
Mutations:{
    incrementCount(state,payload){
        state.counter+=payload.count
    }
}
state:{
    info:{
        name:'pshdhx6',
        age:40,
        height:170
    }
}

这些属性加入到了响应式系统中,而响应式系统会监听属性的变化。当属性变化时,会通知所有界面中用到该属性的地方,让界面刷新;

updateInfo(state){
    state.info.name='pshdhx7'        //因为name在info中原本就要,所以会响应式改变;包括Devtools
    state.info['address']= '洛杉矶' //因为info中原本没有,所以Devtools不会添加此变量
}

这时需要加入到

Vue.set(state.info,'address','洛杉矶'); //这时变量就添加到了Devtools中
updateInfo(state){
    //该方法做不到响应式
    delete state.info.age
    //该方法可以做到响应式
    Vue.delete(state.info,'age')
}

如果在Mutations中使用了异步请求,那么Devtools中的变量将不会得到响应;

所以要将异步请求加入到Actions中

actions:{
    aUpdateInfo(){
        //context:上下文
        setTimeout(()=>{
            context.commit('updateInfo')
        },1000)
    }
}

这时在App.vue中要这样调用Actions中的方法

methods:{
    updateInof(){
        //this.$store.dispatch('aupdateInfo');
        this.$store.dispatch('aupdateinfo','我是payload');
        //为了可以获得异步请求的调用结果
        this.$store.dispatch('aupdateInfo',()=>{
            console.log('异步请求已经调用完成')
        })

        //也可以这样写:
        this.$store.dispatch('aupdateInfo',{
            payload:'我是携带的信息',
            success:()=>{
                console.log('异步请求已经调用完成');
            }
        })
    }
}

在Actions中我们这样写:

actions:{
    aupdateInfo(context,payload){
        setTimeout(()=>{
            context.commit('updateInfo');
            console.log(payload.message);
            payload.success();
        },1000)
    }
}

//或者用promise这样写
actions:{
    aupdateInfo(context,payload){
        return new Promise((resolve,reject)=>{
            setTimeout(()=>{
                context.commit('updateInfo')
                console.log(payload);
                resolve('11111');
            },1000)
        })
    }
}

因为用了在actions中用了promise,这样可以咋app.vue中调用then回调函数

this.$store.dispatch('aupdateInfo','我是携带的信息').then(res=>{
    console.log('里面完成了提交');
    console.log(res);
})

初使用Modules

module是模块的意思,为什么在Vuex中要使用模块呢?

Vue使用单一状态树,那么也就意味着很多状态都会交给Vuex来管理;

当应用变得非常复杂时,store对象就有可能变得非常臃肿;

为了解决这个问题,Vuex允许我们将store分割成模块Module,而每个模块拥有自己的state,mutations,actions,getters等;

const moduleA = {
    state:{},
    mutations:{},
    actions:{},
    getters:{}
},
const moduleB = {
    state:{},
    mutations:{},
    actions:{},
    getters:{}
},
const store = new Vuex.Store({
    modules:{
        a:moduleA,
        b:moduleB
    }
})

store.state.a  //->moduleA的状态
store.state.b  //->moduleB的状态

moduleA就是state中的一个对象;

我们可以这样使用:

{{this.$store.state.a.name}}
const moduleA = {
    state:{
        name:'pshdhx A'
    },
    mutations:{
        updateName(state,payload){
            state.name = payload
        }
    },
    actions:{},
    getters:{
        fullName(state){
            return state.name+'1111'
        },
        fullNames(state,getters){
            return getters.fullName+'2222'
        },
        funllName3(state,getters,rootState){
            return getters.fullName2+rootState.counter
        }
    }
}

App.vue

methods:{
    updateName(){
        this.$store.commit('updateName','lisi');
    }
}

<h2>{{$store.getters.fullName}}</h2>
const moduleA = {
    state:{
        name:'zhangsan'
    },
    mutations:{
        updateName(state,payload){
            state.name = payload
        }
    },
    actions:{
        aupdateName(context){
            setTimeout(()=>{
                context.commit('updateName','wangwu');
            },1000)
        }
    }
}

App.vue
methods:{
    asyncUpdateName(){
        this.$store.dispatch('aupdateName');
    }
}

dispatch对象

actions的写法

const moduleA = {
    actions:{
        increment({state,commit,rootState}){
            if((state.count+rootState.count)%2===1){
                commit('increment')
            }
        }
    }
}

如果getters中也需要使用全局的状态,可以接受更多的参数

const moduleA = {
    getters:{
        withRootCount(state,getters,rootState){
            return state.count = rootState.count
        }
    }
}

vuex的项目结构

引入文件的时候注意:

如果是export的是default,那么可以直接import .. from '..';
如果不是,那么需要import {...} from '..';


import mutations from './mutations'
import actions from './actions'
import getters from './getters'

const store = new Vuex.Store({
    state,
    mutations,
    actions,
    getters
})

 

Logo

前往低代码交流专区

更多推荐