Vuex

141 阅读2分钟

vuex是什么

1.概念:

专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应 用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方 式,且适用于任意组件间通信

2.Github地址:

github.com/vuejs/vuex

什么时候使用Vuex

  • 多个组件依赖于同一状态
  • 来自不同组件的行为需要变更同一状态

不用vuex时

1.jpg

使用vuex

2.jpg

vuex.png

Vuex工作原理

vue Components:组件实例

State:存储数据的

Actions:异步操作,条件

Mutations:修改数据

Backend API:异步操作,发网络请求,逻辑判断

Devtools:开发调式工具

dispatch:调用actions里面的函数

commit:调用mutaions里面的函数

mutate:去修改数据

reder:渲染组件

组件要修改数据,当有异步操作时,先用dispatch方法调用actions里面的函数,actions把异步的操作做完后,用commit方法调用mutaions里面的函数。没有异步操作时,直接用commit方法调用mutaions里面的函数

actions,mutations,state三个组合起来为store,store里面有dispatch和commit方法

<template>
	<div>
		<h1>当前求和为:{{sum}}</h1>
		<select v-model.number="n">
			<option value="1">1</option>
			<option value="2">2</option>
			<option value="3">3</option>
			<!-- 
				默认选择的是字符串,无法进行算术运算
				解决方法一:
				加 : ,当做js表达式
				<option :value="1">1</option>
				解决方法二:
				添加修饰符
				<select v-model.number="n">
			-->
		</select>
		<button @click="increment">+</button>
		<button @click="decrement">-</button>
		<button @click="incrementOdd">当前求和为奇数再加</button>
		<button @click="incrementWait">等一等再加</button>
	</div>
</template>

<script>
	export default {
		name:'Count',
		data() {
			return {
				n:1, //用户选择的数字
				sum:0 //当前的和
			}
		},
		methods: {
			increment(){
				this.sum += this.n
			},
			decrement(){
				this.sum -= this.n
			},
			incrementOdd(){
				if(this.sum % 2){
					this.sum += this.n
				}
			},
			incrementWait(){
				setTimeout(()=>{
					this.sum += this.n
				},500)
			},
		},
	}
</script>

<style lang="css">
	button{
		margin-left: 5px;
	}
</style>

使用vuex

vue2中,要用vuex的3版本

vue3中,要用vuex的4版本

cnpm i vuex@3

在src文件夹添加store文件夹添加index.js

//index.js 该文件用于创建Vuex中最为核心的store

import Vue from 'vue'

//引入Vuex
import Vuex from 'vuex'

//应用Vuex插件
Vue.use(Vuex)

//准备state——用于存储数据
const state={}

//准备actions——用于响应组件中的动作
const actions={}

//准备mutations——用于操作数据(state)
const mutations={}

//创建并暴露store
export default new Vuex.Store({
	actions,
	mutations,
	state,
})

main.js

//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'

//引入store
import store from './store'

//创建vm
new Vue({
	el:'#app',
	render: h => h(App),
	store
})

State

const state={
	sum:0
}

组件中使用:

<h1>{{this.$store.state.sum}}</h1>
<h1>{{$store.state.sum}}</h1>
computed:{
	aa(){
		return this.$store.state.sum
	}
}

Getters

相当于computed

添加一个getters对象

const getters={
	bigSum(state){
		return state.sum*10
	}
}
export default new Vuex.Store({
	actions,
	mutations,
	state,
	getters
})

组件中:

<h1>{{$store.getters.bigbigSum}}</h1>
computed:{
	bb(){
		return this.$store.getters.bigSum
	}
}

Actions/Mutations

组件中:

data() {
	return {
		n:1, //用户选择的数字
	}
},
methods: {
	increment(){
        //this:当前组件上有store.commit方法
        //调用actions里的JIA函数,并传入参数n
        
        //经过actions用dispatch
		this.$store.dispatch('jia',this.n)
        
        //不经过actions用commit
        this.$store.commit('JIA',this.n)
	}
    
},

vuex:

const actions={
    //actions里的函数用小写
    /*
	jia:function(){
		console.log('actions中的jia被调用了')
	}
	*/
    //简写:
    jia(context,value){
        //context:上下文,一个小型的stroe,里面有commit,dispatch,getters等方法
        //value,传入的参数
        console.log('actions中的jia被调用了')
        //调用mutations里的JIA,并把参数传入
        context.commit('JIA',value)
        
        // 有操作的:
        setTimeout(()=>{
		context.commit('JIA',value)
	},500)
                
        if(context.state.sum % 2){
		context.commit('JIA',value)
	}
        
        //传到自己actions的demo1函数,分开处理多个异步操作
        context.dispatch('demo1',value)
        
        //context.state.sum+=vaule
        //可以实现,但是不建议这样,开发者工具只监视mutations的
        
    },
    demo1(context,value){
        if(context.state.sum%2){
            context.commit('JIA',value+1)
        }
    }
}

/*======================Mutations=========================*/
//准备mutations——用于操作数据(state)
const mutations={
    //mutations里的函数用大写
	JIA(state,value){
        //state:vuex中的state
        //value:参数
		console.log('mutations中的JIA被调用了')
		state.sum += value
	}
}

mapState/mapGetters

import {mapState,mapGetters} from 'vuex'

computed:{
    /*================State=========================*/
    //靠程序员自己亲自去写计算属性
    sum(){
        return this.$store.state.sum
    }
    
    //mapState({he:'sum'}):返回的是一个对象,一个对象中不能包含一个对象,用解构赋值 ...
    //去找state中属性名为sum,并改名为he
    
    //对象写法,可以改名
    ...mapState({he:'sum'}) 
    
    //数组写法,当我们不想改名时
    ...mapState(['sum'])
    
    /*===============Getters==========================*/
    //靠程序员自己亲自去写计算属性
    bigSum(){
        return this.$store.getters.bigSum
    }
    
    //对象写法,可以改名
    ...mapState({bigSum:'bigSum'})
    
    //数组写法,当我们不想改名时
    ...mapState(['bigSum'])
}
mounted(){
    const x = mapState({he:'sum'})
	console.log(x)
    //返回的是一个对象
    //{he:function(){}}
}

mapmutations/mapActions

import {mapMutations,mapActions} from 'vuex'

methods: {
    /*===============mutations==========================*/
	//程序员亲自写方法
	increment(){
		this.$store.commit('JIA',this.n)
        },
	
	//对象写法,可以改名,调用是记得传参,例如:@click='JIA(n)'
	...mapMutations({increment:'JIA'}),

	//数组写法,当我们不想改名时
	...mapMutations(['JIA']),

	/*===============Actions==========================*/
	incrementOdd(){
		this.$store.dispatch('jiaOdd',this.n)
	},

	///对象写法,可以改名
	...mapActions({incrementOdd:'jia'})
    
        //数组写法,当我们不想改名时
	...mapActions(['jia']),
}

模块化开发

c.js模块

//c.js
export default {
    namespaced:true,
    actions:{
        addPersonServer(context){
		axios.get('url').then(
			response => {
				context.commit('ADD',response.data)
			},
			error => {
				alert(error.message)
			}
		)
	}
    },
    mutations:{
        ADD(state,value){
            this.data=value
        }
    },
    state:{
        data:[]
    },
    getters:{}
}
//index.js 该文件用于创建Vuex中最为核心的store

import Vue from 'vue'

//引入Vuex
import Vuex from 'vuex'

//应用Vuex插件
Vue.use(Vuex)

//求和相关的配置
const countOptions={
    namespaced:true,
    //...mapState('a',['sum'])
    //能认得这个a,使用时,才能像上面取出来
    actions:{},
    mutations:{},
    state:{
        sum:0
    },
    getters:{}
}

//人员管理相关的配置
const personOptions={
    namespaced:true,
    actions:{},
    mutations:{},
    state:{
        sum:5
    },
    getters:{}
}
import c from './c'
export default new Vuex.Store({
    modules:{
        //a:countOptions
        //b:personOptions
        //countOptions:countOptions
        //简写:
        countOptions,
        personOptions,
        c
    }
})
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
computed:{
    /*================State/Getters=========================*/
    //靠程序员自己亲自去写计算属性
    sum(){
        //return this.$store.state.a.sum
        return this.$store.state.countOptions.sum
    }
    
	//...mapState(['a','b'])
    // {{a.sum}}  {{b.sum}}
    
    //数组写法,当我们不想改名时
    //得配置 namespaced:true
    //...mapState('a',['sum'])
    //...mapState('b',['sum'])
    //{{sum}}
    
    //对象写法,可以改名
    //得配置 namespaced:true
    ...mapState('countOptions',{he:'sum'}) 
    
	//mapGetters是一样的
    //都得配置 namespaced:true
    //在对象/数组前面加一个 模块名 这样一个参数
}
methods:{
    //靠程序员自己亲自去方法时
    add(value){
        this.$store.comm('a/Add',value)
    }
}

总结

自己手写调用:

模块化下的state的属性:return this.$store.state.模块名.属性名

模块化下的getters的属性:return this.$store.state['模块名/属性名']

模块化下的actions的方法:return this.$store.dispatch('模块名/方法名')

模块化下的mutations的方法:return this.$store.commit('模块名/方法名',参数)

map:

...mapxxxx('模块名',['属性名'])

...mapxxxx('模块名',{新属性名:'属性名'})

...mapxxxx('模块名',['方法名'])

...mapxxxx('模块名',{新方法名:'方法名'})