状态管理模式 - vuex的使用介绍

812 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

前言

大家好,不知道大家在用vue进行开发过程中有没有遇到这样一种场景,就是有些时候一些数据是一种通用的共享数据(比如登录信息),那么这类数据在各个组件模块中可能都会用到,如果每个组件中都去后台重新获取那么势必会造成性能浪费,为了解决这一问题一个新的状态管理工具 - vux就应运而生了。那么vuex到底是个什么东西呢,它又是怎么实现数据共享的呢?接下来就跟大家共同学习一下。

了解vuex

官方给出的解释是:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。其实可以简单理解为:将多个组件共享的变量全部存储在一个对象里面,然后将这个对象放在顶层的 Vue 实例中,让其他组件可以使用,它最大的特点是响应式

vuex有如下五个核心模块:

state

  • 用于存放组件间互相通信的属性值。
  • 原则上state中的属性只能在各个组件之间使用,而不能修改,如果要修改需要在mutations中修改
//伪代码
//定义
export default new Vuex.Store({
    state:{
        userinfo:{name:'Alvin'}
    }
})

//使用
this.$store.state.userinfo.name

mutations

  • 这里存放的都是一些函数,用于修改state中的属性值
  • 这里的函数中只接收两个参数:state和options
  • 原则上这里面的函数必须都是同步的
  • 如果某组件中需要修改state中的属性值,则需在该组件中用this.$store.commit('方法名', 参数)的方式来调用,即需要用commit方法来调用mutations中的函数
  • 通过commit触发
//伪代码
//定义
export default new Vuex.Store({
    mutations:{
        changeUserInfo(state,name){
            state.userinfo.name = name;
        }
    }
})

//使用
this.$store.commit("changeUserInfo", "Yannis")

actions

  • 这里存放的也都是一些函数,这里的函数可以是异步的
  • 这里的函数也是接收两个参数:store和options
  • 如果这里的函数想要修改state中的值,还是得通过调用mutations中的方法来实现
  • 如果想要在组件中调用这里的函数,则需要用dispatch方法调用:this.$store.dispatch('方法名', options)
  • 通过dispatch触发

getters

  • 这里也是一些函数,类似于组件中的计算属性
  • 可以处理一些通用且复杂的逻辑, 实际使用比较少

modules

  • 用于划分模块
  • 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store对象显得会相当臃肿
  • 为了解决上面的问题,Vuex允许将store分割成模块。每个模块拥有自己的state、mutation、action、getter甚至是嵌套子模块
  • 如果模块中的mutations或actions重复,则两个重复的方法都会执行
  • 如果想区分模块中重复的mutations或actions,则可以在模块中加一个属性:namespace:true即可,调用时需要指定模块名,例如:this.$store.commit('模块名/方法名')

基于vuex的原理模拟部分Vuex源码

let Vue = null;
function install(_Vue){
	Vue = _Vue;
	Vue.mixin({
		beforeCreate(){
			if(this.$options.store){
				//说明是根实例
				this$store = this.$options.$store
			}else if(this.$parent){
				//有$parent属性,说明这个组件是根组件的后代组件
				this.$store = this.$parent.$store
			}
		}
	});
}

class Store{
	constructor(options){
		//this.state = options.state;//没有响应式
		let vm = new Vue({
			data:{
				state: options.state
			}
		});
		this.state = vm.state;
		this.mutations = {};
		let mutations = options.mutations || {};
		Object.keys(mutations).forEach(key => {
			this.mutations[key] = (option) => {
				mutations[key].call(this,this.state, option);
			}
		});
	
		this.actions = {};
		let actions = options.actions || {};
		Object.keys(actions).forEach(key => {
			this.actions[key] = (option) => {
				actions[key].call(this, this.store, option);
			}
		});

		this.getters = {};
		let getters = options.getters || {};
		Object.keys(getters ).forEach(key => {
			Object.defineProperty(this.getters, key, {
				get:() => {
					return getters[key].call(this, this.state);
				}
			})
		});
	
		this.commit = (type, option) => {
			this.mutations[type](option);	
		}
		
		this.dispatch = (type, option) => {
			this.actions[type](option);
		}
	}
	/*
	* commit 和 dispatch应该是stote私有的
	commit(type, option){
		this.mutations[type](option );
	}
	
	dispatch(type, option){
		this.actions[type](option);
	}
	*/
}

//辅助函数
export function mapState(arr){
	let obj = {};
	arr.forEach(key => {
		obj[key] =  function(){
			return this.$store.state[key]
		}
	});
	return obj;
}

export function mapMutation(arr){
	let obj = {};
	arr.forEach(key => {
		obj[key] =  function(option){
			return this.$store.commit(key, option)
		}
	});
	return obj;
}

export default {
	install,
	Store
}

总结

本次分享中我们共同学习了vue中的状态管理模式 - vuex,最后还用重写vuex的方式简单梳理了一下vuex的实现过程,关于具体的实现原理我们会在以后的分享中详细描述。今天的分享就到这里了。