Vue使用(六) vue状态管理——Vuex(上)-张柏沛IT博客

正文内容

Vue使用(六) vue状态管理——Vuex(上)

栏目:Web前端 发布时间:2019-12-04 16:44 浏览量:178

什么是Vuex

按照vuex官网上的说法:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。


官方文档:
https://vuex.vuejs.org/zh/


我们知道,父组件的数据共享到子组件很简单,只需要使用props属性

子组件的数据想回传到父组件就要使用事件的方式来传递

但是如果是兄弟组件之间传递数据就需要用到vuex

Vuex就是为了让各个不相关的组件能够共用一份数据而设计的

这里介绍几个概念:state,mutations,actions
公共的数据就放在state中,但在组件中不能直接操作和获取里面的数据。而mutations的作用是用来定义如何操作state里面数据,但是mutations只是定义了如何操作。想要执行这个操作就需要用到actions,actions会执行commit,这样数据就会被操作改变


接下来我们实现一下:


1.安装vuex
npm install vuex 


2.src目录下创建store.js


#store.js
import Vue from 'vue'
import Vuex from "vuex"

Vue.use(Vuex)

//state放数据
const state = {
	count:1
}

//mutations定义操作
const mutations = {
	add(state){   //定义操作的方法,方法名自定义
		state.count++
	},
	decrease(state){
		state.count--
	}
}

//actions 执行操作,但是定义actions不会执行操作,触发了actions才会
const actions = {
	add:({commit})=>{  //解构赋值
		commit("add")    //就会执行mutations中的add
	},
	decrease:({commit})=>{
		commit("decrease")
	}
}

//要将state,mutations,actions导出,组件才能使用
export default new Vuex.Store({
	state,mutations,actions
})

PS:上面actions中,正常的写法应该是
add:(context)=>{
    content.commit("add")
}

这个context对象是一个与 store 实例具有相同方法和属性的对象,但不是store本身

这里使用了解构参数之后,相当于 let {commit} = context
把context的commit方法单独赋值给了commit,再传入add()中


3.在入口文件main.js中:

import store from './store'

new Vue({
  el: '#app',
  router,
  store,       //这里要加上store
  components: { App },
  template: '<App/>'
})


PS:这里的store在每个子组件的data中存在,但是访问的时候要加一个$才能访问到;
比如,我在下面的count.js子组件中使用{{$store.state.xxx}}来访问到store的state
在方法中可以 this.$store.state.xxx 来访问到state


4.创建一个子组件components/count.vue

 
<template>
	<div>
		<button type="button" @click="add">增加</button>
		<button type="button" @click="decrease">减少</button>
		
		count数:{{$store.state.count}}
	</div>
</template>

<script>
	import {mapActions} from 'vuex'
	export default {
		methods:mapActions([  //将store.js中的add操作和这里的methods做关联,这样上面的按钮一点击就会分发actions中的add方法,相当于this.$store.dispatch("add"),他就会调用store.js中的actions中的add方法
			'add',
			'decrease'
		])
	}
</script>



//从上面可以看出,可以使用$store.state来访问state中的数据,这里面的数据是各个组件的公共数据
当然你要在main.js中的new Vue({store})中加入store。

我们也可以通过手动执行store的commit()或者dispatch()方法来调用mutation中的操作
上面在methods中使用mapActions()等价于:

methods:{
  add(){
	this.$store.dispatch("add")
  },
  decrease(){
	this.$store.dispatch("decrease")
  }
}


也可以将上面的methods改写为:

methods:{
  add(){
	this.$store.commit("add")
  },
  decrease(){
	this.$store.commit("decrease")
  }
}


commit()和dispatch()的区别是,前者是mutations提交,后者是actions分发。如果你的store.js中没有定义actions,那么你就只能用mutations提交(commit)

实际上,上面mapActions也可以写成mapMutations,只不过这样就变成使用mutations提交而不是actions分发了:

methods:mapMutations([  
    'add',
    'decrease'
]);


那么使用actions分发和使用mutations提交他们效果是一样的,都是会操作state中的数据的改变,但区别是,在actions中定义的方法可以是异步的,而后者是只能同步的,所以像异步请求这种事只能由actions提交

在mutations中定义的方法可以有第二参,这个第二参就是mutations的载荷
这个第二参放对象的话就相当于是传很多很多参数了

const mutations = {
  increment (state, payload) {
    state.count += payload.amount
  }
}



//commit的时候传入
store.commit("increment",{amount:10})  //这个{amount:10}就是作为第二参传入到payload

//或者你可以这样传
store.commit({
  type: 'increment',
  amount: 10
})


使用action分发:


actions分发:
store.dispatch("add")  

dispatch一样可以传入载荷参数
store.dispatch("add",100)

下面拿之前的store.js来举例

import Vue from 'vue'
import Vuex from "vuex"

Vue.use(Vuex)

//state放数据
const state = {
	count:1
}

//mutations定义操作
const mutations = {
	add(state){   //定义操作的方法,方法名自定义
		state.count++
	},
	decrease(state){
		state.count--
	}
}

//actions 执行操作,但是定义actions不会执行操作,触发了actions才会
const actions = {
	add:({commit})=>{  //解构赋值
		commit("add")    //就会执行mutations中的add
	},
	decrease:({commit})=>{
		commit("decrease")
	}
}

//要将state,mutations,actions导出,组件才能使用
export default new Vuex.Store({
	state,mutations,actions
})



当我在子组件中执行 this.$store.dispatch("add") 时:

会调用actions中的add方法,actions中的add方法会调用 commit() 而让mutations执行mutations中的add方法。


actions中的方法要做的只有一件事,就是commit提交,从而出发mutations中的方法。
但是mutations可以通过this.$store.commit()提交,为什么还要用this.$store.dispatch()分发呢,后者相当于多绕了一个弯子
原因是actions中的方法可以是异步的。

actions 中的方法可以返回Promise对象,这样的话当调用dispatch方法的时候,他会调用actions中的方法,然后返回Promise对象,所以dispatch返回的也是promise对象,这么一来就可以使用async 和 await 了。可以在store.dispatch前面加await。

比如:

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}


在子组件中:

methods:{
	async doActionA(){
		await this.$store.dispatch("actionA")   //返回值为空,因为resolve()中没有内容
		
		console.log("someMutation操作已经完成")
	}
}


如果您需要转载,可以点击下方按钮可以进行复制粘贴;本站博客文章为原创,请转载时注明以下信息

张柏沛IT技术博客 > Vue使用(六) vue状态管理——Vuex(上)

热门推荐
推荐新闻