更多优质内容
请关注公众号

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

正文内容

Vue使用(七) vue状态管理——Vuex(下)

栏目:Web前端 系列:Vue的简单使用系列 发布时间:2019-12-04 17:03 浏览量:2096

state与计算属性的配合

这两个会经常配合在一起,以上一节中的 state.count 为例子,我现在想根据state.count获取一个big_count=count*100

最简单的做法:


computed:{
  big_count(){
	return this.$store.state.count*100
  }
}


当然,还可以使用mapState辅助函数

import {mapState} from "vuex"

computed:mapState({
	big_count:(state)=>{ 
		return state.count*100
	}
})


如果 big_count 就是 state.count 那么可以简写为

computed:mapState({
	big_count:"count"
})


如果连计算属性的属性名也和state.count的属性名相同可以:

computed:mapState(["count"])


但是使用了mapState之后,那么如何定义属于该子组件本身的计算属性(局部计算属性)?
可以使用对象展开运算符(即...):

data(){
	return {
		num:5
	}
},
computed:{
	numSquare(){   //计算num的平方,局部计算属性
		return this.num * this.num
	},
	...mapState({
		big_count:"count"
	})
}

所以上面使用 mapActions的时候一样可以用对象展开运算符来定义该子组件自己的事件方法


如果有很多个子组件,对state.count这个数据都要用到同一个计算属性的话,为了不必在每个子组件都定义一次计算属性,vuex有个getter的概念可以实现

用法如下:
在 store.js 中定义getters变量

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

Vue.use(Vuex)

const state={
  count:1
}

const mutations={
  //...
}

const actions={
  //...
}

const getters = {
  big_count:(state,getters)=>{  //第二参可以不传,第二参中包含getters中的所有计算属性
    return state.count*100
  }
}


export default new Vuex.Store({
  state,mutations,actions,getters
})


在模板调用:

{{$store.getters.big_count}}


如果你不想在子组件的模板中写成
{{$store.getters.big_count}}
这个样子的话,可以将state.getters给映射到局部计算属性中

import {mapGetters} from 'vuex'
computed:{
	...mapGetters([
		"big_count"
	])
}


Vuex中的modules概念:

现在考虑一种情况,有多个页面,他们各自需要自己的store容器,此时只有一个store.js 是不够的。这里就需要用到vuex中的modules模块

在src下创建一个store目录,store下面创建如下文件

modules
    |-a.js 
    |-b.js 
index.js


// # a.js
const state={
	money:1
}

const mutations = {
	add(state){
		state.money++
	},
	reduce(state){
		state.money--
	}
}

const actions = {
	add:({commit})=>{
		commit('add')
	},
	reduce:({commit})=>{
		commit("reduce")
	}
	
}

export default {
	namespace:true,  //使用命名空间
	state,
	mutations,
	actions
}


// # b.js
const state={
	count:1
}

const mutations = {
	add(state,n){
		state.count+=n
	},
	reduce(state,n){
		state.count-=n
	}
}

const actions = {
	add:({commit},n)=>{
		commit('add',n)
	},
	reduce:({commit},n)=>{
		commit("reduce",n)
	}	
}

export default {
	namespaced:true,  //使用命名空间,否则后面用mapActions和mapState传入第一参会失效
	state,
	mutations,
	actions
}


在这两个文件里只定义了state,actions,mutations ,没有执行Vue.use(Vuex)

// # index.js 
import Vue from "vue"
import Vuex from "vuex"
import money from "./modules/a"
import count from "./modules/b"

Vue.use(Vuex)

export default new Vuex.Store({
	modules:{
		money,count     //模块名
	}
})


在index.js中导出Store仓库,这里是以modules的方式导出,这样可以导出多个仓库。

然后再在main.js中引入store

// # main.js 
import store from "./store/index.js"

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


现在创建两个页面,在components目录中创建

A.vue 
B.vue 


在router目录中的index.js定义两个路由

{
	path:"/a",
	name:"A",
	component:A
},
{
	path:"/b",
	name:"B",
	component:B
}



<!-- # A.vue -->

<template>
	<div>
		A.vue 
		<div>
			<p>{{$store.state.money.money}}</p>
			<button type="button" @click="add">+</button>
			<button type="button" @click="reduce">-</button>
		</div>
	</div>
</template>

<script>
import {mapActions} from "vuex"
	export default {
		computed:{
			...mapState("money",['money'])    //如果不想写$store.state.money.money那么长,可以使用mapState映射
		},
		methods:(
			...mapActions("money",["add","reduce"])
		)
	}
</script>


在A组件中操控money模块的money属性,调用的时候{{$store.state.模块名.属性名}},模块名就是new Vuex.Store({})中导出的模块名。
使用mapActions执行分发操作的时候,也要在第一参注明模块名(store的命名空间),第二参是方法名,是个数组或者对象

B.vue也依法炮制count模块

<!--  B.vue  -->

<template>
	<div>
		B.vue 
		<div>
			<p>{{$store.state.count.count}}</p>
			<button type="button" @click="add(2)">+</button>
			<button type="button" @click="reduce(2)">-</button>
		</div>
	</div>
</template>

<script>
import {mapActions} from "vuex"
	export default {
		
		methods:(
			...mapActions("count",["add","reduce"])    //第一参指明模块名,其实是store的命名空间
		)
	}
</script>


B.vue这里我还传了参数,因为count的mutations中是有定义载荷的。

当然,B也可以操作money模块,A也能操作count模块


PS:如果需要手动分发的话,在指定了namespaced为true的情况下,需要指定分发的模块

this.$store.dispatch("count/add");

如果没有指定namespaced为true 那么 

this.$store.dispatch("add");

即可

更多关于vuex的内容请查看官方文档手册





更多内容请关注微信公众号
zbpblog微信公众号

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

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

热门推荐
推荐新闻