Vue学习之状态管理—Vuex的详细使用


前言

我们知道,父组件通过prop向子组件传递数据,子组件通过定义事件向父组件传递数据。但假若遇到多个组件访问统一数据时,就需要一个全局的状态管理方案vuex来解决。

Vuex是一个专为Vue.js应用程序开发的状态管理模式。它采用集中式存储来管理应用程序中所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex也集成到了调式工具vue-devTools中,提供了一些高级调试功能。

一、安装Vuex

使用NPM安装方式,在命令行中输入:

npm install vuex --save

在Vue脚手架项目中使用,在main.js文件中导入Vuex,并使用Vue.use()来安装插件。

//main.js
import Vue from 'vue'
import axios from 'vuex'

Vue.use(Vuex) //安装插件

二、核心概念

1.store

每一个Vuex应用的核心就是store,它可以理解为保持应用程序状态的容器。store与普通的全局对象区别有以下两点:

1.Vuex的状态存储是响应式的。当Vue组件从store中检索状态时,如果store的状态发生变化,那么组件也会得到及时更新
2.不能直接改变store中的状态。改变store中的状态的唯一途径是显示地提交mutation

在创建store前先了解下vuex的工作原理。
vuex的工作原理图
我们可以将虚线框理解成是store,可以看到store里面包含了Actions、Mutations、State三个函数,每个函数都有不同作用。

Actions可以实现异步或批量操作,Mutation中放的是要对state中数据修改的内容,State是用来存储全局公用的数据。若要改变组件数据,必须通过Mutations(可以略过Actions)。

由图可知,可以通过Commit方法来调用Mutations,通过Mutate方法来调用State,通过Dispatch方法来调用Actions

了解了vuex的工作原理后,我们开始创建store。

1.首先在src下创建store/index.js
在这里插入图片描述
在文件中new一个store实例

export default new Vuex.Store({
  state:{
  	city:'zhuhai'//这里存放的是全局数据city
  }
});

若要在组件中使用city这个数据,用this.$store.state.city调用

<div class="">{{this.$store.state.city}}</div>

2.在main.js文件中引入store,并在创建根vue实例的时候将store传入进去

//main.js
import store from "./store(store的路径)"
new Vue({
  router,
  store,//在此添加
})

2.mutations

mutations是当我们需要修改state中的数据时必须用到的,而在没有异步/批量操作时actions可用可不用

1.首先在组件中用Dispatch()来调用Actions

methods:{
	handleCityClick(city){
		this.$store.dispatch('changeCity',city)//派发一个名为changeCity的actions对象
	}
}

2.在store/index.js里写一个actions对象

export default new Vuex.Store({
  state:{
  	city:'zhuhai'//这里存放的是全局数据city
  },
  actions: {
  //这里的city就是从组件中dispatch传过来的,ctx为上下文对象
    changeCity(ctx, city) {
      ctx.commit("changeCity", city);//用commit来调用Mutations
    },
    Mutations:{
    	changeCity (state,city){
    		state.city=city//将新传过来的city赋值给state.city
    	}
    }
  }, 
  modules: {}
});

如果不用actions,则直接在组件方法中调用this.$store.commit()即可

3.mapState

当一个组件需要使用多个store状态属性时,将这些状态都声明为计算属性就会显得重复和冗余。为了解决这个问题,可以使用mapState辅助函数帮助我们生成计算属性。

import { mapState } from 'Vuex'
export default {
	//...
	computed:{
		//1.单个数据
		//...mapState(['city'])
		//2.数组写法
		...mapState({
			currentcity:'city'
		})
	}
}

通过mapState,把公用数据映射到city后,调用数据的写法从this.$store.state.city变为this.city。
同理,mapMutations也是辅助函数简化mutation的提交,用法和mapState一样。

4.getter

getter类似computed,当需要根据state中的数据算出新数据时,借助getter来提供新数据。

假如在store的状态中定义了一个图书数组,代码如下:

export default new Vuex.Store({
	state:{
	 books:[
	 	{id:1,title:'vuex getter',isSold:false},
	 	{id:2,title:'book',isSold:true}
	 	]
	 },
	 ...
})

在组件内需要得到正在销售的图书,于是定义一个计算属性sellingBooks,对state中的books进行过滤。代码如下:

computed:{
	sellingBooks(){
		return this.$store.state.book.filter(book=>book.isSold === true);
	}
}

如果多个组件都需要用到sellingBooks属性,无论是复制代码还是抽取为共享函数导入都不理想。这时我们可以在store中定义getters它的返回值会根据它的依赖项被缓存起来,且只有在它的依赖项发生改变时才会重新计算

getter接受state作为其第一个参数,代码如下:

export default new Vuex.Store({
	state:{
	 books:[
	 	{id:1,title:'vuex getter',isSold:false},
	 	{id:2,title:'book',isSold:true}
	 	]
	 },
	 getters:{
	 	sellingBooks:state => state.books.filter(book => book.isSold == true)
	 }
})

我们定义的getter将作为store.getters对象的属性来访问,代码如下:

<ul>
	<li v-for="book in this.$store.getters.sellingBooks" :key="book.id">
		{{book.title}}
	</li>
</ul>

getter也可以接收其他getter作为第二参数。

getters:{
	sellingBooks:state => state.books.filter(book => book.isSold == true),
	sellingBooksCount:(state,getters)=>{
		return getters.sellingBooks.length
	}
}

如果要简化上述getter计算属性的访问方式(this.$store.getters.sellingBooks),可以使用mapGetters,用法同mapState类似。

computed:{
	//传递数组作为参数
	...mapGetters([
		'sellingBooks',
		'sellingBooksCount',
		...
	]),
	//传递对象作为参数
	..mapGetters({
		booksCount:'sellingBooksCount'
	})
}

5.module

当应用程序复杂时,store对象就会非常臃肿,为了方便管理,将store划分为多个模块,每个模块包含自己的state、mutations、actions、getters,以及嵌套的子模块。

const moduleA = {
	state:{...},
	mutations:{...},
	actions:{...},
	getters:{...}
}

const moduleB = {
	state:{...},
	mutations:{...},
	actions:{...},
	getters:{...}
}
...
const store = new Vuex.Store({
	modules:{
		a:modulesA,
		b:modulesB
		}
})
获取状态:
store.state.a
store.state.b

模块内部状态

const moduleA = {
	state:{count:0},
	mutations:{increment(state){
		state.count++//state对象是局部模块状态
		}
	},
	getters:{
		doubleCount (state) {
			return state.count*2
			}
		}
}

总结

本文介绍了Vuex的使用,要注意的是,不要直接去修改store中的状态,而应该通过mutations来修改,在组件内,mutation是映射为组件的方法来使用的,而store中的state和getter是映射为计算属性来使用的,store中的action也是映射为组件的方法来使用的。如果应用比较复杂,可以使用module模块化管理,同时访问也会变得复杂。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值