如何使用Vuex


npm install vuex --save-dev //安装vuex
// src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.store({
	state:{

	},
	mutation:{

	},
	action:{

	},
	getter:{

	},
	module:{

	}
})

export default store


// main.js
import store from './store'

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

Vuex.store需要传入的各个属性:

state

state封装Vuex需要管理的状态;
单一状态树(不建议new两个或以上的store)

//例子:
const store = new Vuex.store({
	state:{
		counter:1000
	},
	...
})


//访问state中的状态
{{ $store.state.counter }}

//修改state中的状态
"$store.state.counter++"  //不建议直接修改,直接修改尽管也是响应式的,
						  //但是这样的修改方式无法被devtools追踪到,不便于后期的调试
//那么应该怎样修改?

首先看一幅图:
在这里插入图片描述
这是官方建议的修改方式,我们从最下方的紫色的State开始看起,State借由Render可以在Vue Components上进行展示,而Vue Components需要通过分配Actions,然后commitMutations,最后通过Mutations的Mutate行为来修改State。

可以看到,在Mutations处向外延伸连接到了一个Devtools,这是一个Vue官方的浏览器插件,它的作用正是追踪修改,保存修改记录的。

那么为什么不直接从Vue Components指向Mutations呢?为什么还要再多走一步Actions呢?

这里要区分清楚,其实从Vue Components指向Mutations也是可以的,只是这样的修改方式只适用于同步操作,如果是异步操作的话,就必须要经过Actions,否则的话Devtools将追踪不到异步操作的记录。

从图中可以清楚的看到,Actions通过Backend API将异步操作转换为同步操作,之后再传入到Mutations,这样就能被Devtools追踪到了。

需要注意的是,Devtools是一个浏览器插件,使用之前需要先在浏览器上安装。

所以如果是同步操作的话,正确的修改方式是:

const store = new Vuex.store({
	state:{  //定义状态
		counter:1000
	},
	mutations:{  //定义方法
		increment(state){  //默认参数state
			state.counter++
		},
		decrement(state){
			state.counter--
		}
	},
	...
})

this.$store.commit('incremnet')  //通过这种方法调用mutations中定义的方法
this.$store.commit('decremnet')  

getters

getters类似于一个计算属性,当我们需要获取state中的一些变异数据,并且这种数据多个组件都需要用到时,推荐使用getters。

const store = new Vuex.store({
	state:{  
		counter:1000
		students:[
			{id:100,name:'Jack'},
			{id:101,name:'Tom'},
			{id:102,name:'Jane'}
		]
	},
	getters:{
		getPowercounter(state){  //默认第一个参数为state
			return state.counter * state.counter
		},
		getIdgt101(state){  //获取id大于101的学生
			return state.students.filter(s => s.id > 101)
		},
		getIdgt101Length(state,getter){  //获取id大于101的学生的数量,这里可传入第二个默认参数getters
			return getter.getIdgt101.length
		},
		getIds(state){  //获取id大于指定id的学生,不能在这里传入id,第二个参数传入的不管是什么都被指向getters
			return id => {
				return state.students.filter(s => s.id > id)
			}
		}
	}
	...
})

$store.getters.getIdgt101  //调用getter中的方法
$store.getters.getIds(100)

mutations

Vuex官方指定,对状态的更改必须要经过mutations,这里要注意区分getters与mutations,getters是对状态的异变但这种异变不会作用于state中,即状态本身是没有改变的,只是呈现出来的变了,而mutations是改变了state中的状态。

mutations:{
	increment(state){  //默认传入state参数

	},
	increment(state,count){  //需要传入其它参数时,放在后面

	},
	increment(state,obj){  //传入多个参数时,以对象的形式放在state后面

	}
}

//调用
//风格1
$store.mutations.commit('increment')
$store.mutations.commit('increment',count)
$store.mutations.commit('increment',obj)

//风格2
$store.mutations.commit({
	type:'increment',
	count   //注意这里的count传入mutations中的increment()方法后是作为对象形式传入的,即应该payload.count这样访问
})

Vuex的响应式注意点

Vuex中管理的状态都是响应式的,但这要有一个前提条件,即这些状态是提前已经定义的,是已经初始化过的并封装在state中的,比如说:

state:{
	info:{name:'lihua',age:18}
}

这个info当然是响应式的,我们对info中的数据即name和age不管做什么更改都会立即呈现在页面上,但如果我们想要往info中添加一个新属性,你就会发现,属性虽然在后台确实添加进了info中,但它不是响应式的,这是因为新属性并没有事先被定义,所以它不会被添加到Vue的响应式系统中。

那么这时,我们又确实希望这种行为也能是响应式的,那么该怎么办呢?

方法如下:

Vue.set(state.info,grade,2018)  //响应式的添加一个新属性
Vue.delete(state.info,name)  //响应式的删除一个属性

actions

如果是同步操作,那么直接经由mutations修改状态就可以,但如果是异步操作,之前已经提到,需要先经过actions的一层包装之后,再经由muations修改状态,否则devtools将追踪不到异步操作。

具体用法参考如下:

mutations:{
	updateinfo(state):{
		state.info.name = 'xiaoming'
	}
},
actions:{
	unpadeInfo(context){  //这里也有默认参数,但是context,不是state,context相当于store
		setTimeout(() => {
			context.commit('updateinfo') //这里commit的是mutations中的方法
		},1000)
	}
}

//调用
$store.actions.dispatch('updateInfo')

需要传入参数时,参照:

mutations:{
	updateinfo(state):{
		state.info.name = 'xiaoming'
	}
},
actions:{
	unpadeInfo(context,payload){   //定义第二个参数接受传入的参数,对象类型
		setTimeout(() => {
			context.commit('updateinfo')
			...  //操作payload
		},1000)
	}
}

$store.actions.dispatch('updateInfo',message)  //在这里传入参数

另外,因为actions中封装了一步方法,当我们需要在异步方法中定义回调时,参考如下:

mutations:{
	updateinfo(state):{
		state.info.name = 'xiaoming'
	}
},
actions:{
	unpadeInfo(context,payload){   
		return new Promise((resolve,reject) => {
			setTimeout(() => {
				context.commit('updateinfo')
				...  //操作payload
				resolve() //调用resolve
			},1000)
		})
	}
}

$store.dispatch('updateInfo',message)
	.then(() => {
		...  //回调函数
	})

modules

modules的作用是给Vuex分块,当Vuex管理的状态过多而导致代码或者逻辑混乱时,我们可以在modules中定义新的模块,这些模块与store类似但作为store的一部分,如下:

const store = new Vuex.store({
	state:{},
	mutations:{},
	actions:{},
	getters:{},
	modules:[
		VuexA:{  //VueA模块
			state:{},
			mutations:{},
			actions:{},
			getters:{},	
		},
		VuexB:{
			...
		},
		...
	}
})

//访问Vuex中的state
$store.state.Vuex.***

//对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章